chiark / gitweb /
Prep v228: Add remaining updates from upstream (3/3)
[elogind.git] / src / libelogind / sd-bus / bus-control.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
24 #endif
25
26 #include <errno.h>
27 #include <stddef.h>
28
29 #include "sd-bus.h"
30
31 #include "alloc-util.h"
32 #include "bus-bloom.h"
33 #include "bus-control.h"
34 #include "bus-internal.h"
35 #include "bus-message.h"
36 #include "bus-util.h"
37 #include "capability-util.h"
38 #include "stdio-util.h"
39 #include "string-util.h"
40 #include "strv.h"
41 #include "user-util.h"
42
43 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
44         int r;
45
46         assert_return(bus, -EINVAL);
47         assert_return(unique, -EINVAL);
48         assert_return(!bus_pid_changed(bus), -ECHILD);
49
50         if (!bus->bus_client)
51                 return -EINVAL;
52
53         r = bus_ensure_running(bus);
54         if (r < 0)
55                 return r;
56
57         *unique = bus->unique_name;
58         return 0;
59 }
60
61 static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
62         struct kdbus_cmd *n;
63         size_t size, l;
64         int r;
65
66         assert(bus);
67         assert(name);
68
69         l = strlen(name) + 1;
70         size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
71         n = alloca0_align(size, 8);
72         n->size = size;
73         n->flags = request_name_flags_to_kdbus(flags);
74
75         n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
76         n->items[0].type = KDBUS_ITEM_NAME;
77         memcpy(n->items[0].str, name, l);
78
79 #ifdef HAVE_VALGRIND_MEMCHECK_H
80         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
81 #endif
82
83         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
84         if (r < 0)
85                 return -errno;
86
87         if (n->return_flags & KDBUS_NAME_IN_QUEUE)
88                 return 0;
89
90         return 1;
91 }
92
93 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
94         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
95         uint32_t ret, param = 0;
96         int r;
97
98         assert(bus);
99         assert(name);
100
101         if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
102                 param |= BUS_NAME_ALLOW_REPLACEMENT;
103         if (flags & SD_BUS_NAME_REPLACE_EXISTING)
104                 param |= BUS_NAME_REPLACE_EXISTING;
105         if (!(flags & SD_BUS_NAME_QUEUE))
106                 param |= BUS_NAME_DO_NOT_QUEUE;
107
108         r = sd_bus_call_method(
109                         bus,
110                         "org.freedesktop.DBus",
111                         "/org/freedesktop/DBus",
112                         "org.freedesktop.DBus",
113                         "RequestName",
114                         NULL,
115                         &reply,
116                         "su",
117                         name,
118                         param);
119         if (r < 0)
120                 return r;
121
122         r = sd_bus_message_read(reply, "u", &ret);
123         if (r < 0)
124                 return r;
125
126         if (ret == BUS_NAME_ALREADY_OWNER)
127                 return -EALREADY;
128         else if (ret == BUS_NAME_EXISTS)
129                 return -EEXIST;
130         else if (ret == BUS_NAME_IN_QUEUE)
131                 return 0;
132         else if (ret == BUS_NAME_PRIMARY_OWNER)
133                 return 1;
134
135         return -EIO;
136 }
137
138 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
139         assert_return(bus, -EINVAL);
140         assert_return(name, -EINVAL);
141         assert_return(!bus_pid_changed(bus), -ECHILD);
142         assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
143         assert_return(service_name_is_valid(name), -EINVAL);
144         assert_return(name[0] != ':', -EINVAL);
145
146         if (!bus->bus_client)
147                 return -EINVAL;
148
149         /* Don't allow requesting the special driver and local names */
150         if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
151                 return -EINVAL;
152
153         if (!BUS_IS_OPEN(bus->state))
154                 return -ENOTCONN;
155
156         if (bus->is_kernel)
157                 return bus_request_name_kernel(bus, name, flags);
158         else
159                 return bus_request_name_dbus1(bus, name, flags);
160 }
161
162 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
163         struct kdbus_cmd *n;
164         size_t size, l;
165         int r;
166
167         assert(bus);
168         assert(name);
169
170         l = strlen(name) + 1;
171         size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
172         n = alloca0_align(size, 8);
173         n->size = size;
174
175         n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
176         n->items[0].type = KDBUS_ITEM_NAME;
177         memcpy(n->items[0].str, name, l);
178
179 #ifdef HAVE_VALGRIND_MEMCHECK_H
180         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
181 #endif
182         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
183         if (r < 0)
184                 return -errno;
185
186         return 0;
187 }
188
189 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
190         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
191         uint32_t ret;
192         int r;
193
194         assert(bus);
195         assert(name);
196
197         r = sd_bus_call_method(
198                         bus,
199                         "org.freedesktop.DBus",
200                         "/org/freedesktop/DBus",
201                         "org.freedesktop.DBus",
202                         "ReleaseName",
203                         NULL,
204                         &reply,
205                         "s",
206                         name);
207         if (r < 0)
208                 return r;
209
210         r = sd_bus_message_read(reply, "u", &ret);
211         if (r < 0)
212                 return r;
213         if (ret == BUS_NAME_NON_EXISTENT)
214                 return -ESRCH;
215         if (ret == BUS_NAME_NOT_OWNER)
216                 return -EADDRINUSE;
217         if (ret == BUS_NAME_RELEASED)
218                 return 0;
219
220         return -EINVAL;
221 }
222
223 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
224         assert_return(bus, -EINVAL);
225         assert_return(name, -EINVAL);
226         assert_return(!bus_pid_changed(bus), -ECHILD);
227         assert_return(service_name_is_valid(name), -EINVAL);
228         assert_return(name[0] != ':', -EINVAL);
229
230         if (!bus->bus_client)
231                 return -EINVAL;
232
233         /* Don't allow releasing the special driver and local names */
234         if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
235                 return -EINVAL;
236
237         if (!BUS_IS_OPEN(bus->state))
238                 return -ENOTCONN;
239
240         if (bus->is_kernel)
241                 return bus_release_name_kernel(bus, name);
242         else
243                 return bus_release_name_dbus1(bus, name);
244 }
245
246 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
247         struct kdbus_cmd_list cmd = {
248                 .size = sizeof(cmd),
249                 .flags = flags,
250         };
251         struct kdbus_info *name_list, *name;
252         uint64_t previous_id = 0;
253         int r;
254
255         /* Caller will free half-constructed list on failure... */
256
257         r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
258         if (r < 0)
259                 return -errno;
260
261         name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
262
263         KDBUS_FOREACH(name, name_list, cmd.list_size) {
264                 struct kdbus_item *item;
265
266                 if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) {
267                         char *n;
268
269                         if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
270                                 r = -ENOMEM;
271                                 goto fail;
272                         }
273
274                         r = strv_consume(x, n);
275                         if (r < 0)
276                                 goto fail;
277
278                         previous_id = name->id;
279                 }
280
281                 KDBUS_ITEM_FOREACH(item, name, items) {
282                         if (item->type == KDBUS_ITEM_OWNED_NAME) {
283                                 if (service_name_is_valid(item->name.name)) {
284                                         r = strv_extend(x, item->name.name);
285                                         if (r < 0) {
286                                                 r = -ENOMEM;
287                                                 goto fail;
288                                         }
289                                 }
290                         }
291                 }
292         }
293
294         r = 0;
295
296 fail:
297         bus_kernel_cmd_free(bus, cmd.offset);
298         return r;
299 }
300
301 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
302         _cleanup_strv_free_ char **x = NULL, **y = NULL;
303         int r;
304
305         if (acquired) {
306                 r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
307                 if (r < 0)
308                         return r;
309         }
310
311         if (activatable) {
312                 r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
313                 if (r < 0)
314                         return r;
315
316                 *activatable = y;
317                 y = NULL;
318         }
319
320         if (acquired) {
321                 *acquired = x;
322                 x = NULL;
323         }
324
325         return 0;
326 }
327
328 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
329         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
330         _cleanup_strv_free_ char **x = NULL, **y = NULL;
331         int r;
332
333         if (acquired) {
334                 r = sd_bus_call_method(
335                                 bus,
336                                 "org.freedesktop.DBus",
337                                 "/org/freedesktop/DBus",
338                                 "org.freedesktop.DBus",
339                                 "ListNames",
340                                 NULL,
341                                 &reply,
342                                 NULL);
343                 if (r < 0)
344                         return r;
345
346                 r = sd_bus_message_read_strv(reply, &x);
347                 if (r < 0)
348                         return r;
349
350                 reply = sd_bus_message_unref(reply);
351         }
352
353         if (activatable) {
354                 r = sd_bus_call_method(
355                                 bus,
356                                 "org.freedesktop.DBus",
357                                 "/org/freedesktop/DBus",
358                                 "org.freedesktop.DBus",
359                                 "ListActivatableNames",
360                                 NULL,
361                                 &reply,
362                                 NULL);
363                 if (r < 0)
364                         return r;
365
366                 r = sd_bus_message_read_strv(reply, &y);
367                 if (r < 0)
368                         return r;
369
370                 *activatable = y;
371                 y = NULL;
372         }
373
374         if (acquired) {
375                 *acquired = x;
376                 x = NULL;
377         }
378
379         return 0;
380 }
381
382 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
383         assert_return(bus, -EINVAL);
384         assert_return(acquired || activatable, -EINVAL);
385         assert_return(!bus_pid_changed(bus), -ECHILD);
386
387         if (!bus->bus_client)
388                 return -EINVAL;
389
390         if (!BUS_IS_OPEN(bus->state))
391                 return -ENOTCONN;
392
393         if (bus->is_kernel)
394                 return bus_list_names_kernel(bus, acquired, activatable);
395         else
396                 return bus_list_names_dbus1(bus, acquired, activatable);
397 }
398
399 static int bus_populate_creds_from_items(
400                 sd_bus *bus,
401                 struct kdbus_info *info,
402                 uint64_t mask,
403                 sd_bus_creds *c) {
404
405         struct kdbus_item *item;
406         uint64_t m;
407         int r;
408
409         assert(bus);
410         assert(info);
411         assert(c);
412
413         KDBUS_ITEM_FOREACH(item, info, items) {
414
415                 switch (item->type) {
416
417                 case KDBUS_ITEM_PIDS:
418
419                         if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
420                                 c->pid = (pid_t) item->pids.pid;
421                                 c->mask |= SD_BUS_CREDS_PID;
422                         }
423
424                         if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
425                                 c->tid = (pid_t) item->pids.tid;
426                                 c->mask |= SD_BUS_CREDS_TID;
427                         }
428
429                         if (mask & SD_BUS_CREDS_PPID) {
430                                 if (item->pids.ppid > 0) {
431                                         c->ppid = (pid_t) item->pids.ppid;
432                                         c->mask |= SD_BUS_CREDS_PPID;
433                                 } else if (item->pids.pid == 1) {
434                                         /* The structure doesn't
435                                          * really distinguish the case
436                                          * where a process has no
437                                          * parent and where we don't
438                                          * know it because it could
439                                          * not be translated due to
440                                          * namespaces. However, we
441                                          * know that PID 1 has no
442                                          * parent process, hence let's
443                                          * patch that in, manually. */
444                                         c->ppid = 0;
445                                         c->mask |= SD_BUS_CREDS_PPID;
446                                 }
447                         }
448
449                         break;
450
451                 case KDBUS_ITEM_CREDS:
452
453                         if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
454                                 c->uid = (uid_t) item->creds.uid;
455                                 c->mask |= SD_BUS_CREDS_UID;
456                         }
457
458                         if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
459                                 c->euid = (uid_t) item->creds.euid;
460                                 c->mask |= SD_BUS_CREDS_EUID;
461                         }
462
463                         if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
464                                 c->suid = (uid_t) item->creds.suid;
465                                 c->mask |= SD_BUS_CREDS_SUID;
466                         }
467
468                         if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
469                                 c->fsuid = (uid_t) item->creds.fsuid;
470                                 c->mask |= SD_BUS_CREDS_FSUID;
471                         }
472
473                         if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
474                                 c->gid = (gid_t) item->creds.gid;
475                                 c->mask |= SD_BUS_CREDS_GID;
476                         }
477
478                         if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
479                                 c->egid = (gid_t) item->creds.egid;
480                                 c->mask |= SD_BUS_CREDS_EGID;
481                         }
482
483                         if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
484                                 c->sgid = (gid_t) item->creds.sgid;
485                                 c->mask |= SD_BUS_CREDS_SGID;
486                         }
487
488                         if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
489                                 c->fsgid = (gid_t) item->creds.fsgid;
490                                 c->mask |= SD_BUS_CREDS_FSGID;
491                         }
492
493                         break;
494
495                 case KDBUS_ITEM_PID_COMM:
496                         if (mask & SD_BUS_CREDS_COMM) {
497                                 r = free_and_strdup(&c->comm, item->str);
498                                 if (r < 0)
499                                         return r;
500
501                                 c->mask |= SD_BUS_CREDS_COMM;
502                         }
503                         break;
504
505                 case KDBUS_ITEM_TID_COMM:
506                         if (mask & SD_BUS_CREDS_TID_COMM) {
507                                 r = free_and_strdup(&c->tid_comm, item->str);
508                                 if (r < 0)
509                                         return r;
510
511                                 c->mask |= SD_BUS_CREDS_TID_COMM;
512                         }
513                         break;
514
515                 case KDBUS_ITEM_EXE:
516                         if (mask & SD_BUS_CREDS_EXE) {
517                                 r = free_and_strdup(&c->exe, item->str);
518                                 if (r < 0)
519                                         return r;
520
521                                 c->mask |= SD_BUS_CREDS_EXE;
522                         }
523                         break;
524
525                 case KDBUS_ITEM_CMDLINE:
526                         if (mask & SD_BUS_CREDS_CMDLINE) {
527                                 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
528                                 c->cmdline = memdup(item->data, c->cmdline_size);
529                                 if (!c->cmdline)
530                                         return -ENOMEM;
531
532                                 c->mask |= SD_BUS_CREDS_CMDLINE;
533                         }
534                         break;
535
536                 case KDBUS_ITEM_CGROUP:
537                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
538                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
539                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
540
541                         if (m) {
542                                 r = free_and_strdup(&c->cgroup, item->str);
543                                 if (r < 0)
544                                         return r;
545
546                                 r = bus_get_root_path(bus);
547                                 if (r < 0)
548                                         return r;
549
550                                 r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
551                                 if (r < 0)
552                                         return r;
553
554                                 c->mask |= m;
555                         }
556                         break;
557
558                 case KDBUS_ITEM_CAPS:
559                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
560                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
561
562                         if (m) {
563                                 if (item->caps.last_cap != cap_last_cap() ||
564                                     item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
565                                         return -EBADMSG;
566
567                                 c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
568                                 if (!c->capability)
569                                         return -ENOMEM;
570
571                                 c->mask |= m;
572                         }
573                         break;
574
575                 case KDBUS_ITEM_SECLABEL:
576                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
577                                 r = free_and_strdup(&c->label, item->str);
578                                 if (r < 0)
579                                         return r;
580
581                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
582                         }
583                         break;
584
585                 case KDBUS_ITEM_AUDIT:
586                         if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
587                                 c->audit_session_id = (uint32_t) item->audit.sessionid;
588                                 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
589                         }
590
591                         if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
592                                 c->audit_login_uid = (uid_t) item->audit.loginuid;
593                                 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
594                         }
595                         break;
596
597                 case KDBUS_ITEM_OWNED_NAME:
598                         if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
599                                 r = strv_extend(&c->well_known_names, item->name.name);
600                                 if (r < 0)
601                                         return r;
602
603                                 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
604                         }
605                         break;
606
607                 case KDBUS_ITEM_CONN_DESCRIPTION:
608                         if (mask & SD_BUS_CREDS_DESCRIPTION) {
609                                 r = free_and_strdup(&c->description, item->str);
610                                 if (r < 0)
611                                         return r;
612
613                                 c->mask |= SD_BUS_CREDS_DESCRIPTION;
614                         }
615                         break;
616
617                 case KDBUS_ITEM_AUXGROUPS:
618                         if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
619                                 size_t i, n;
620                                 uid_t *g;
621
622                                 n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
623                                 g = new(gid_t, n);
624                                 if (!g)
625                                         return -ENOMEM;
626
627                                 for (i = 0; i < n; i++)
628                                         g[i] = item->data64[i];
629
630                                 free(c->supplementary_gids);
631                                 c->supplementary_gids = g;
632                                 c->n_supplementary_gids = n;
633
634                                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
635                         }
636                         break;
637                 }
638         }
639
640         return 0;
641 }
642
643 int bus_get_name_creds_kdbus(
644                 sd_bus *bus,
645                 const char *name,
646                 uint64_t mask,
647                 bool allow_activator,
648                 sd_bus_creds **creds) {
649
650         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
651         struct kdbus_cmd_info *cmd;
652         struct kdbus_info *conn_info;
653         size_t size, l;
654         uint64_t id;
655         int r;
656
657         if (streq(name, "org.freedesktop.DBus"))
658                 return -EOPNOTSUPP;
659
660         r = bus_kernel_parse_unique_name(name, &id);
661         if (r < 0)
662                 return r;
663         if (r > 0) {
664                 size = offsetof(struct kdbus_cmd_info, items);
665                 cmd = alloca0_align(size, 8);
666                 cmd->id = id;
667         } else {
668                 l = strlen(name) + 1;
669                 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
670                 cmd = alloca0_align(size, 8);
671                 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
672                 cmd->items[0].type = KDBUS_ITEM_NAME;
673                 memcpy(cmd->items[0].str, name, l);
674         }
675
676         /* If augmentation is on, and the bus didn't provide us
677          * the bits we want, then ask for the PID/TID so that we
678          * can read the rest from /proc. */
679         if ((mask & SD_BUS_CREDS_AUGMENT) &&
680             (mask & (SD_BUS_CREDS_PPID|
681                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
682                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
683                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
684                      SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
685                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
686                      SD_BUS_CREDS_SELINUX_CONTEXT|
687                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
688                 mask |= SD_BUS_CREDS_PID;
689
690         cmd->size = size;
691         cmd->attach_flags = attach_flags_to_kdbus(mask);
692
693         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
694         if (r < 0)
695                 return -errno;
696
697         conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
698
699         /* Non-activated names are considered not available */
700         if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
701                 if (name[0] == ':')
702                         r = -ENXIO;
703                 else
704                         r = -ESRCH;
705                 goto fail;
706         }
707
708         c = bus_creds_new();
709         if (!c) {
710                 r = -ENOMEM;
711                 goto fail;
712         }
713
714         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
715                 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
716                         r = -ENOMEM;
717                         goto fail;
718                 }
719
720                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
721         }
722
723         /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
724            them in case the service has no names. This does not mean
725            however that the list of owned names could not be
726            acquired. Hence, let's explicitly clarify that the data is
727            complete. */
728         c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
729
730         r = bus_populate_creds_from_items(bus, conn_info, mask, c);
731         if (r < 0)
732                 goto fail;
733
734         r = bus_creds_add_more(c, mask, 0, 0);
735         if (r < 0)
736                 goto fail;
737
738         if (creds) {
739                 *creds = c;
740                 c = NULL;
741         }
742
743         r = 0;
744
745 fail:
746         bus_kernel_cmd_free(bus, cmd->offset);
747         return r;
748 }
749
750 static int bus_get_name_creds_dbus1(
751                 sd_bus *bus,
752                 const char *name,
753                 uint64_t mask,
754                 sd_bus_creds **creds) {
755
756         _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
757         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
758         const char *unique = NULL;
759         pid_t pid = 0;
760         int r;
761
762         /* Only query the owner if the caller wants to know it or if
763          * the caller just wants to check whether a name exists */
764         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
765                 r = sd_bus_call_method(
766                                 bus,
767                                 "org.freedesktop.DBus",
768                                 "/org/freedesktop/DBus",
769                                 "org.freedesktop.DBus",
770                                 "GetNameOwner",
771                                 NULL,
772                                 &reply_unique,
773                                 "s",
774                                 name);
775                 if (r < 0)
776                         return r;
777
778                 r = sd_bus_message_read(reply_unique, "s", &unique);
779                 if (r < 0)
780                         return r;
781         }
782
783         if (mask != 0) {
784                 c = bus_creds_new();
785                 if (!c)
786                         return -ENOMEM;
787
788                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
789                         c->unique_name = strdup(unique);
790                         if (!c->unique_name)
791                                 return -ENOMEM;
792
793                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
794                 }
795
796                 if ((mask & SD_BUS_CREDS_PID) ||
797                     ((mask & SD_BUS_CREDS_AUGMENT) &&
798                      (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
799                               SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
800                               SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
801                               SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
802                               SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
803                               SD_BUS_CREDS_SELINUX_CONTEXT|
804                               SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
805
806                         uint32_t u;
807
808                         r = sd_bus_call_method(
809                                         bus,
810                                         "org.freedesktop.DBus",
811                                         "/org/freedesktop/DBus",
812                                         "org.freedesktop.DBus",
813                                         "GetConnectionUnixProcessID",
814                                         NULL,
815                                         &reply,
816                                         "s",
817                                         unique ? unique : name);
818                         if (r < 0)
819                                 return r;
820
821                         r = sd_bus_message_read(reply, "u", &u);
822                         if (r < 0)
823                                 return r;
824
825                         pid = u;
826                         if (mask & SD_BUS_CREDS_PID) {
827                                 c->pid = u;
828                                 c->mask |= SD_BUS_CREDS_PID;
829                         }
830
831                         reply = sd_bus_message_unref(reply);
832                 }
833
834                 if (mask & SD_BUS_CREDS_EUID) {
835                         uint32_t u;
836
837                         r = sd_bus_call_method(
838                                         bus,
839                                         "org.freedesktop.DBus",
840                                         "/org/freedesktop/DBus",
841                                         "org.freedesktop.DBus",
842                                         "GetConnectionUnixUser",
843                                         NULL,
844                                         &reply,
845                                         "s",
846                                         unique ? unique : name);
847                         if (r < 0)
848                                 return r;
849
850                         r = sd_bus_message_read(reply, "u", &u);
851                         if (r < 0)
852                                 return r;
853
854                         c->euid = u;
855                         c->mask |= SD_BUS_CREDS_EUID;
856
857                         reply = sd_bus_message_unref(reply);
858                 }
859
860                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
861                         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
862                         const void *p = NULL;
863                         size_t sz = 0;
864
865                         r = sd_bus_call_method(
866                                         bus,
867                                         "org.freedesktop.DBus",
868                                         "/org/freedesktop/DBus",
869                                         "org.freedesktop.DBus",
870                                         "GetConnectionSELinuxSecurityContext",
871                                         &error,
872                                         &reply,
873                                         "s",
874                                         unique ? unique : name);
875                         if (r < 0) {
876                                 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
877                                         return r;
878                         } else {
879                                 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
880                                 if (r < 0)
881                                         return r;
882
883                                 c->label = strndup(p, sz);
884                                 if (!c->label)
885                                         return -ENOMEM;
886
887                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
888                         }
889                 }
890
891                 r = bus_creds_add_more(c, mask, pid, 0);
892                 if (r < 0)
893                         return r;
894         }
895
896         if (creds) {
897                 *creds = c;
898                 c = NULL;
899         }
900
901         return 0;
902 }
903
904 _public_ int sd_bus_get_name_creds(
905                 sd_bus *bus,
906                 const char *name,
907                 uint64_t mask,
908                 sd_bus_creds **creds) {
909
910         assert_return(bus, -EINVAL);
911         assert_return(name, -EINVAL);
912         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
913         assert_return(mask == 0 || creds, -EINVAL);
914         assert_return(!bus_pid_changed(bus), -ECHILD);
915         assert_return(service_name_is_valid(name), -EINVAL);
916
917         if (!bus->bus_client)
918                 return -EINVAL;
919
920         if (streq(name, "org.freedesktop.DBus.Local"))
921                 return -EINVAL;
922
923         if (!BUS_IS_OPEN(bus->state))
924                 return -ENOTCONN;
925
926         if (bus->is_kernel)
927                 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
928         else
929                 return bus_get_name_creds_dbus1(bus, name, mask, creds);
930 }
931
932 static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
933         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
934         struct kdbus_cmd_info cmd = {
935                 .size = sizeof(struct kdbus_cmd_info),
936         };
937         struct kdbus_info *creator_info;
938         pid_t pid = 0;
939         int r;
940
941         c = bus_creds_new();
942         if (!c)
943                 return -ENOMEM;
944
945         /* If augmentation is on, and the bus doesn't didn't allow us
946          * to get the bits we want, then ask for the PID/TID so that we
947          * can read the rest from /proc. */
948         if ((mask & SD_BUS_CREDS_AUGMENT) &&
949             (mask & (SD_BUS_CREDS_PPID|
950                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
951                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
952                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
953                      SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
954                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
955                      SD_BUS_CREDS_SELINUX_CONTEXT|
956                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
957                 mask |= SD_BUS_CREDS_PID;
958
959         cmd.attach_flags = attach_flags_to_kdbus(mask);
960
961         r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
962         if (r < 0)
963                 return -errno;
964
965         creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
966
967         r = bus_populate_creds_from_items(bus, creator_info, mask, c);
968         bus_kernel_cmd_free(bus, cmd.offset);
969         if (r < 0)
970                 return r;
971
972         r = bus_creds_add_more(c, mask, pid, 0);
973         if (r < 0)
974                 return r;
975
976         *ret = c;
977         c = NULL;
978         return 0;
979 }
980
981 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
982         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
983         pid_t pid = 0;
984         bool do_label;
985         int r;
986
987         assert(bus);
988
989         do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
990
991         /* Avoid allocating anything if we have no chance of returning useful data */
992         if (!bus->ucred_valid && !do_label)
993                 return -ENODATA;
994
995         c = bus_creds_new();
996         if (!c)
997                 return -ENOMEM;
998
999         if (bus->ucred_valid) {
1000                 if (bus->ucred.pid > 0) {
1001                         pid = c->pid = bus->ucred.pid;
1002                         c->mask |= SD_BUS_CREDS_PID & mask;
1003                 }
1004
1005                 if (bus->ucred.uid != UID_INVALID) {
1006                         c->euid = bus->ucred.uid;
1007                         c->mask |= SD_BUS_CREDS_EUID & mask;
1008                 }
1009
1010                 if (bus->ucred.gid != GID_INVALID) {
1011                         c->egid = bus->ucred.gid;
1012                         c->mask |= SD_BUS_CREDS_EGID & mask;
1013                 }
1014         }
1015
1016         if (do_label) {
1017                 c->label = strdup(bus->label);
1018                 if (!c->label)
1019                         return -ENOMEM;
1020
1021                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1022         }
1023
1024         r = bus_creds_add_more(c, mask, pid, 0);
1025         if (r < 0)
1026                 return r;
1027
1028         *ret = c;
1029         c = NULL;
1030         return 0;
1031 }
1032
1033 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
1034         assert_return(bus, -EINVAL);
1035         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
1036         assert_return(ret, -EINVAL);
1037         assert_return(!bus_pid_changed(bus), -ECHILD);
1038
1039         if (!BUS_IS_OPEN(bus->state))
1040                 return -ENOTCONN;
1041
1042         if (bus->is_kernel)
1043                 return bus_get_owner_creds_kdbus(bus, mask, ret);
1044         else
1045                 return bus_get_owner_creds_dbus1(bus, mask, ret);
1046 }
1047
1048 static int add_name_change_match(sd_bus *bus,
1049                                  uint64_t cookie,
1050                                  const char *name,
1051                                  const char *old_owner,
1052                                  const char *new_owner) {
1053
1054         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
1055         int is_name_id = -1, r;
1056         struct kdbus_item *item;
1057
1058         assert(bus);
1059
1060         /* If we encounter a match that could match against
1061          * NameOwnerChanged messages, then we need to create
1062          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1063          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1064          * multiple if the match is underspecified.
1065          *
1066          * The NameOwnerChanged signals take three parameters with
1067          * unique or well-known names, but only some forms actually
1068          * exist:
1069          *
1070          * WELLKNOWN, "", UNIQUE       â†’ KDBUS_ITEM_NAME_ADD
1071          * WELLKNOWN, UNIQUE, ""       â†’ KDBUS_ITEM_NAME_REMOVE
1072          * WELLKNOWN, UNIQUE, UNIQUE   â†’ KDBUS_ITEM_NAME_CHANGE
1073          * UNIQUE, "", UNIQUE          â†’ KDBUS_ITEM_ID_ADD
1074          * UNIQUE, UNIQUE, ""          â†’ KDBUS_ITEM_ID_REMOVE
1075          *
1076          * For the latter two the two unique names must be identical.
1077          *
1078          * */
1079
1080         if (name) {
1081                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1082                 if (is_name_id < 0)
1083                         return 0;
1084         }
1085
1086         if (!isempty(old_owner)) {
1087                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1088                 if (r < 0)
1089                         return 0;
1090                 if (r == 0)
1091                         return 0;
1092                 if (is_name_id > 0 && old_owner_id != name_id)
1093                         return 0;
1094         } else
1095                 old_owner_id = KDBUS_MATCH_ID_ANY;
1096
1097         if (!isempty(new_owner)) {
1098                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1099                 if (r < 0)
1100                         return r;
1101                 if (r == 0)
1102                         return 0;
1103                 if (is_name_id > 0 && new_owner_id != name_id)
1104                         return 0;
1105         } else
1106                 new_owner_id = KDBUS_MATCH_ID_ANY;
1107
1108         if (is_name_id <= 0) {
1109                 struct kdbus_cmd_match *m;
1110                 size_t sz, l;
1111
1112                 /* If the name argument is missing or is a well-known
1113                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1114                  * matches for it */
1115
1116                 l = name ? strlen(name) + 1 : 0;
1117
1118                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1119                             offsetof(struct kdbus_item, name_change) +
1120                             offsetof(struct kdbus_notify_name_change, name) +
1121                             l);
1122
1123                 m = alloca0_align(sz, 8);
1124                 m->size = sz;
1125                 m->cookie = cookie;
1126
1127                 item = m->items;
1128                 item->size =
1129                         offsetof(struct kdbus_item, name_change) +
1130                         offsetof(struct kdbus_notify_name_change, name) +
1131                         l;
1132
1133                 item->name_change.old_id.id = old_owner_id;
1134                 item->name_change.new_id.id = new_owner_id;
1135
1136                 if (name)
1137                         memcpy(item->name_change.name, name, l);
1138
1139                 /* If the old name is unset or empty, then
1140                  * this can match against added names */
1141                 if (isempty(old_owner)) {
1142                         item->type = KDBUS_ITEM_NAME_ADD;
1143
1144                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1145                         if (r < 0)
1146                                 return -errno;
1147                 }
1148
1149                 /* If the new name is unset or empty, then
1150                  * this can match against removed names */
1151                 if (isempty(new_owner)) {
1152                         item->type = KDBUS_ITEM_NAME_REMOVE;
1153
1154                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1155                         if (r < 0)
1156                                 return -errno;
1157                 }
1158
1159                 /* The CHANGE match we need in either case, because
1160                  * what is reported as a name change by the kernel
1161                  * might just be an owner change between starter and
1162                  * normal clients. For userspace such a change should
1163                  * be considered a removal/addition, hence let's
1164                  * subscribe to this unconditionally. */
1165                 item->type = KDBUS_ITEM_NAME_CHANGE;
1166                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1167                 if (r < 0)
1168                         return -errno;
1169         }
1170
1171         if (is_name_id != 0) {
1172                 struct kdbus_cmd_match *m;
1173                 uint64_t sz;
1174
1175                 /* If the name argument is missing or is a unique
1176                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1177                  * for it */
1178
1179                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1180                             offsetof(struct kdbus_item, id_change) +
1181                             sizeof(struct kdbus_notify_id_change));
1182
1183                 m = alloca0_align(sz, 8);
1184                 m->size = sz;
1185                 m->cookie = cookie;
1186
1187                 item = m->items;
1188                 item->size =
1189                         offsetof(struct kdbus_item, id_change) +
1190                         sizeof(struct kdbus_notify_id_change);
1191                 item->id_change.id = name_id;
1192
1193                 /* If the old name is unset or empty, then this can
1194                  * match against added ids */
1195                 if (isempty(old_owner)) {
1196                         item->type = KDBUS_ITEM_ID_ADD;
1197                         if (!isempty(new_owner))
1198                                 item->id_change.id = new_owner_id;
1199
1200                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1201                         if (r < 0)
1202                                 return -errno;
1203                 }
1204
1205                 /* If thew new name is unset or empty, then this can
1206                  * match against removed ids */
1207                 if (isempty(new_owner)) {
1208                         item->type = KDBUS_ITEM_ID_REMOVE;
1209                         if (!isempty(old_owner))
1210                                 item->id_change.id = old_owner_id;
1211
1212                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1213                         if (r < 0)
1214                                 return -errno;
1215                 }
1216         }
1217
1218         return 0;
1219 }
1220
1221 int bus_add_match_internal_kernel(
1222                 sd_bus *bus,
1223                 struct bus_match_component *components,
1224                 unsigned n_components,
1225                 uint64_t cookie) {
1226
1227         struct kdbus_cmd_match *m;
1228         struct kdbus_item *item;
1229         uint64_t *bloom;
1230         size_t sz;
1231         const char *sender = NULL;
1232         size_t sender_length = 0;
1233         uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
1234         bool using_bloom = false;
1235         unsigned i;
1236         bool matches_name_change = true;
1237         const char *name_change_arg[3] = {};
1238         int r;
1239
1240         assert(bus);
1241
1242         /* Monitor streams don't support matches, make this a NOP */
1243         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1244                 return 0;
1245
1246         bloom = alloca0(bus->bloom_size);
1247
1248         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1249
1250         for (i = 0; i < n_components; i++) {
1251                 struct bus_match_component *c = &components[i];
1252
1253                 switch (c->type) {
1254
1255                 case BUS_MATCH_SENDER:
1256                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1257                                 matches_name_change = false;
1258
1259                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1260                         if (r < 0)
1261                                 return r;
1262                         else if (r > 0)
1263                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1264                         else  {
1265                                 sender = c->value_str;
1266                                 sender_length = strlen(sender);
1267                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1268                         }
1269
1270                         break;
1271
1272                 case BUS_MATCH_MESSAGE_TYPE:
1273                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1274                                 matches_name_change = false;
1275
1276                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1277                         using_bloom = true;
1278                         break;
1279
1280                 case BUS_MATCH_INTERFACE:
1281                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1282                                 matches_name_change = false;
1283
1284                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1285                         using_bloom = true;
1286                         break;
1287
1288                 case BUS_MATCH_MEMBER:
1289                         if (!streq(c->value_str, "NameOwnerChanged"))
1290                                 matches_name_change = false;
1291
1292                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1293                         using_bloom = true;
1294                         break;
1295
1296                 case BUS_MATCH_PATH:
1297                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1298                                 matches_name_change = false;
1299
1300                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1301                         using_bloom = true;
1302                         break;
1303
1304                 case BUS_MATCH_PATH_NAMESPACE:
1305                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1306                         using_bloom = true;
1307                         break;
1308
1309                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1310                         char buf[sizeof("arg")-1 + 2 + 1];
1311
1312                         if (c->type - BUS_MATCH_ARG < 3)
1313                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1314
1315                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1316                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1317                         using_bloom = true;
1318                         break;
1319                 }
1320
1321                 case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
1322                         char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
1323
1324                         xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
1325                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1326                         using_bloom = true;
1327                         break;
1328                 }
1329
1330                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
1331                         /*
1332                          * XXX: DBus spec defines arg[0..63]path= matching to be
1333                          * a two-way glob. That is, if either string is a prefix
1334                          * of the other, it matches.
1335                          * This is really hard to realize in bloom-filters, as
1336                          * we would have to create a bloom-match for each prefix
1337                          * of @c->value_str. This is excessive, hence we just
1338                          * ignore all those matches and accept everything from
1339                          * the kernel. People should really avoid those matches.
1340                          * If they're used in real-life some day, we will have
1341                          * to properly support multiple-matches here.
1342                          */
1343                         break;
1344
1345                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1346                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1347
1348                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1349                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1350                         using_bloom = true;
1351                         break;
1352                 }
1353
1354                 case BUS_MATCH_DESTINATION:
1355                         /*
1356                          * Kernel only supports matching on destination IDs, but
1357                          * not on destination names. So just skip the
1358                          * destination name restriction and verify it in
1359                          * user-space on retrieval.
1360                          */
1361                         r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
1362                         if (r < 0)
1363                                 return r;
1364                         else if (r > 0)
1365                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1366
1367                         /* if not a broadcast, it cannot be a name-change */
1368                         if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
1369                                 matches_name_change = false;
1370
1371                         break;
1372
1373                 case BUS_MATCH_ROOT:
1374                 case BUS_MATCH_VALUE:
1375                 case BUS_MATCH_LEAF:
1376                 case _BUS_MATCH_NODE_TYPE_MAX:
1377                 case _BUS_MATCH_NODE_TYPE_INVALID:
1378                         assert_not_reached("Invalid match type?");
1379                 }
1380         }
1381
1382         if (using_bloom)
1383                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1384
1385         m = alloca0_align(sz, 8);
1386         m->size = sz;
1387         m->cookie = cookie;
1388
1389         item = m->items;
1390
1391         if (src_id != KDBUS_MATCH_ID_ANY) {
1392                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1393                 item->type = KDBUS_ITEM_ID;
1394                 item->id = src_id;
1395                 item = KDBUS_ITEM_NEXT(item);
1396         }
1397
1398         if (dst_id != KDBUS_MATCH_ID_ANY) {
1399                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1400                 item->type = KDBUS_ITEM_DST_ID;
1401                 item->id = dst_id;
1402                 item = KDBUS_ITEM_NEXT(item);
1403         }
1404
1405         if (using_bloom) {
1406                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1407                 item->type = KDBUS_ITEM_BLOOM_MASK;
1408                 memcpy(item->data64, bloom, bus->bloom_size);
1409                 item = KDBUS_ITEM_NEXT(item);
1410         }
1411
1412         if (sender) {
1413                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1414                 item->type = KDBUS_ITEM_NAME;
1415                 memcpy(item->str, sender, sender_length + 1);
1416         }
1417
1418         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1419         if (r < 0)
1420                 return -errno;
1421
1422         if (matches_name_change) {
1423
1424                 /* If this match could theoretically match
1425                  * NameOwnerChanged messages, we need to
1426                  * install a second non-bloom filter explitly
1427                  * for it */
1428
1429                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1430                 if (r < 0)
1431                         return r;
1432         }
1433
1434         return 0;
1435 }
1436
1437 #define internal_match(bus, m)                                          \
1438         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1439          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1440          : (m))
1441
1442 static int bus_add_match_internal_dbus1(
1443                 sd_bus *bus,
1444                 const char *match) {
1445
1446         const char *e;
1447
1448         assert(bus);
1449         assert(match);
1450
1451         e = internal_match(bus, match);
1452
1453         return sd_bus_call_method(
1454                         bus,
1455                         "org.freedesktop.DBus",
1456                         "/org/freedesktop/DBus",
1457                         "org.freedesktop.DBus",
1458                         "AddMatch",
1459                         NULL,
1460                         NULL,
1461                         "s",
1462                         e);
1463 }
1464
1465 int bus_add_match_internal(
1466                 sd_bus *bus,
1467                 const char *match,
1468                 struct bus_match_component *components,
1469                 unsigned n_components,
1470                 uint64_t cookie) {
1471
1472         assert(bus);
1473
1474         if (!bus->bus_client)
1475                 return -EINVAL;
1476
1477         if (bus->is_kernel)
1478                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1479         else
1480                 return bus_add_match_internal_dbus1(bus, match);
1481 }
1482
1483 int bus_remove_match_internal_kernel(
1484                 sd_bus *bus,
1485                 uint64_t cookie) {
1486
1487         struct kdbus_cmd_match m = {
1488                 .size = offsetof(struct kdbus_cmd_match, items),
1489                 .cookie = cookie,
1490         };
1491         int r;
1492
1493         assert(bus);
1494
1495         /* Monitor streams don't support matches, make this a NOP */
1496         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1497                 return 0;
1498
1499         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1500         if (r < 0)
1501                 return -errno;
1502
1503         return 0;
1504 }
1505
1506 static int bus_remove_match_internal_dbus1(
1507                 sd_bus *bus,
1508                 const char *match) {
1509
1510         const char *e;
1511
1512         assert(bus);
1513         assert(match);
1514
1515         e = internal_match(bus, match);
1516
1517         return sd_bus_call_method(
1518                         bus,
1519                         "org.freedesktop.DBus",
1520                         "/org/freedesktop/DBus",
1521                         "org.freedesktop.DBus",
1522                         "RemoveMatch",
1523                         NULL,
1524                         NULL,
1525                         "s",
1526                         e);
1527 }
1528
1529 int bus_remove_match_internal(
1530                 sd_bus *bus,
1531                 const char *match,
1532                 uint64_t cookie) {
1533
1534         assert(bus);
1535
1536         if (!bus->bus_client)
1537                 return -EINVAL;
1538
1539         if (bus->is_kernel)
1540                 return bus_remove_match_internal_kernel(bus, cookie);
1541         else
1542                 return bus_remove_match_internal_dbus1(bus, match);
1543 }
1544
1545 /// UNNEEDED by elogind
1546 #if 0
1547 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1548         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1549         const char *mid;
1550         int r;
1551
1552         assert_return(bus, -EINVAL);
1553         assert_return(name, -EINVAL);
1554         assert_return(machine, -EINVAL);
1555         assert_return(!bus_pid_changed(bus), -ECHILD);
1556         assert_return(service_name_is_valid(name), -EINVAL);
1557
1558         if (!bus->bus_client)
1559                 return -EINVAL;
1560
1561         if (!BUS_IS_OPEN(bus->state))
1562                 return -ENOTCONN;
1563
1564         if (streq_ptr(name, bus->unique_name))
1565                 return sd_id128_get_machine(machine);
1566
1567         r = sd_bus_message_new_method_call(
1568                         bus,
1569                         &m,
1570                         name,
1571                         "/",
1572                         "org.freedesktop.DBus.Peer",
1573                         "GetMachineId");
1574         if (r < 0)
1575                 return r;
1576
1577         r = sd_bus_message_set_auto_start(m, false);
1578         if (r < 0)
1579                 return r;
1580
1581         r = sd_bus_call(bus, m, 0, NULL, &reply);
1582         if (r < 0)
1583                 return r;
1584
1585         r = sd_bus_message_read(reply, "s", &mid);
1586         if (r < 0)
1587                 return r;
1588
1589         return sd_id128_from_string(mid, machine);
1590 }
1591 #endif // 0