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