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