chiark / gitweb /
99115d5e492f4157ee3722bc51a4e60131d63b8a
[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         bool do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
983
984         /* Avoid allocating anything if we have no chance of returning useful data */
985         if (!bus->ucred_valid && !do_label)
986                 return -ENODATA;
987
988         c = bus_creds_new();
989         if (!c)
990                 return -ENOMEM;
991
992         if (bus->ucred_valid) {
993                 if (bus->ucred.pid > 0) {
994                         pid = c->pid = bus->ucred.pid;
995                         c->mask |= SD_BUS_CREDS_PID & mask;
996                 }
997
998                 if (bus->ucred.uid != UID_INVALID) {
999                         c->euid = bus->ucred.uid;
1000                         c->mask |= SD_BUS_CREDS_EUID & mask;
1001                 }
1002
1003                 if (bus->ucred.gid != GID_INVALID) {
1004                         c->egid = bus->ucred.gid;
1005                         c->mask |= SD_BUS_CREDS_EGID & mask;
1006                 }
1007         }
1008
1009         if (do_label) {
1010                 c->label = strdup(bus->label);
1011                 if (!c->label)
1012                         return -ENOMEM;
1013
1014                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1015         }
1016
1017         r = bus_creds_add_more(c, mask, pid, 0);
1018         if (r < 0)
1019                 return r;
1020
1021         *ret = c;
1022         c = NULL;
1023         return 0;
1024 }
1025
1026 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
1027         assert_return(bus, -EINVAL);
1028         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
1029         assert_return(ret, -EINVAL);
1030         assert_return(!bus_pid_changed(bus), -ECHILD);
1031
1032         if (!BUS_IS_OPEN(bus->state))
1033                 return -ENOTCONN;
1034
1035         if (bus->is_kernel)
1036                 return bus_get_owner_creds_kdbus(bus, mask, ret);
1037         else
1038                 return bus_get_owner_creds_dbus1(bus, mask, ret);
1039 }
1040
1041 static int add_name_change_match(sd_bus *bus,
1042                                  uint64_t cookie,
1043                                  const char *name,
1044                                  const char *old_owner,
1045                                  const char *new_owner) {
1046
1047         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
1048         int is_name_id = -1, r;
1049         struct kdbus_item *item;
1050
1051         assert(bus);
1052
1053         /* If we encounter a match that could match against
1054          * NameOwnerChanged messages, then we need to create
1055          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1056          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1057          * multiple if the match is underspecified.
1058          *
1059          * The NameOwnerChanged signals take three parameters with
1060          * unique or well-known names, but only some forms actually
1061          * exist:
1062          *
1063          * WELLKNOWN, "", UNIQUE       → KDBUS_ITEM_NAME_ADD
1064          * WELLKNOWN, UNIQUE, ""       → KDBUS_ITEM_NAME_REMOVE
1065          * WELLKNOWN, UNIQUE, UNIQUE   → KDBUS_ITEM_NAME_CHANGE
1066          * UNIQUE, "", UNIQUE          → KDBUS_ITEM_ID_ADD
1067          * UNIQUE, UNIQUE, ""          → KDBUS_ITEM_ID_REMOVE
1068          *
1069          * For the latter two the two unique names must be identical.
1070          *
1071          * */
1072
1073         if (name) {
1074                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1075                 if (is_name_id < 0)
1076                         return 0;
1077         }
1078
1079         if (!isempty(old_owner)) {
1080                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1081                 if (r < 0)
1082                         return 0;
1083                 if (r == 0)
1084                         return 0;
1085                 if (is_name_id > 0 && old_owner_id != name_id)
1086                         return 0;
1087         } else
1088                 old_owner_id = KDBUS_MATCH_ID_ANY;
1089
1090         if (!isempty(new_owner)) {
1091                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1092                 if (r < 0)
1093                         return r;
1094                 if (r == 0)
1095                         return 0;
1096                 if (is_name_id > 0 && new_owner_id != name_id)
1097                         return 0;
1098         } else
1099                 new_owner_id = KDBUS_MATCH_ID_ANY;
1100
1101         if (is_name_id <= 0) {
1102                 struct kdbus_cmd_match *m;
1103                 size_t sz, l;
1104
1105                 /* If the name argument is missing or is a well-known
1106                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1107                  * matches for it */
1108
1109                 l = name ? strlen(name) + 1 : 0;
1110
1111                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1112                             offsetof(struct kdbus_item, name_change) +
1113                             offsetof(struct kdbus_notify_name_change, name) +
1114                             l);
1115
1116                 m = alloca0_align(sz, 8);
1117                 m->size = sz;
1118                 m->cookie = cookie;
1119
1120                 item = m->items;
1121                 item->size =
1122                         offsetof(struct kdbus_item, name_change) +
1123                         offsetof(struct kdbus_notify_name_change, name) +
1124                         l;
1125
1126                 item->name_change.old_id.id = old_owner_id;
1127                 item->name_change.new_id.id = new_owner_id;
1128
1129                 if (name)
1130                         memcpy(item->name_change.name, name, l);
1131
1132                 /* If the old name is unset or empty, then
1133                  * this can match against added names */
1134                 if (!old_owner || old_owner[0] == 0) {
1135                         item->type = KDBUS_ITEM_NAME_ADD;
1136
1137                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1138                         if (r < 0)
1139                                 return -errno;
1140                 }
1141
1142                 /* If the new name is unset or empty, then
1143                  * this can match against removed names */
1144                 if (!new_owner || new_owner[0] == 0) {
1145                         item->type = KDBUS_ITEM_NAME_REMOVE;
1146
1147                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1148                         if (r < 0)
1149                                 return -errno;
1150                 }
1151
1152                 /* The CHANGE match we need in either case, because
1153                  * what is reported as a name change by the kernel
1154                  * might just be an owner change between starter and
1155                  * normal clients. For userspace such a change should
1156                  * be considered a removal/addition, hence let's
1157                  * subscribe to this unconditionally. */
1158                 item->type = KDBUS_ITEM_NAME_CHANGE;
1159                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1160                 if (r < 0)
1161                         return -errno;
1162         }
1163
1164         if (is_name_id != 0) {
1165                 struct kdbus_cmd_match *m;
1166                 uint64_t sz;
1167
1168                 /* If the name argument is missing or is a unique
1169                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1170                  * for it */
1171
1172                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1173                             offsetof(struct kdbus_item, id_change) +
1174                             sizeof(struct kdbus_notify_id_change));
1175
1176                 m = alloca0_align(sz, 8);
1177                 m->size = sz;
1178                 m->cookie = cookie;
1179
1180                 item = m->items;
1181                 item->size =
1182                         offsetof(struct kdbus_item, id_change) +
1183                         sizeof(struct kdbus_notify_id_change);
1184                 item->id_change.id = name_id;
1185
1186                 /* If the old name is unset or empty, then this can
1187                  * match against added ids */
1188                 if (!old_owner || old_owner[0] == 0) {
1189                         item->type = KDBUS_ITEM_ID_ADD;
1190                         if (!isempty(new_owner))
1191                                 item->id_change.id = new_owner_id;
1192
1193                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1194                         if (r < 0)
1195                                 return -errno;
1196                 }
1197
1198                 /* If thew new name is unset or empty, then this can
1199                  * match against removed ids */
1200                 if (!new_owner || new_owner[0] == 0) {
1201                         item->type = KDBUS_ITEM_ID_REMOVE;
1202                         if (!isempty(old_owner))
1203                                 item->id_change.id = old_owner_id;
1204
1205                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1206                         if (r < 0)
1207                                 return -errno;
1208                 }
1209         }
1210
1211         return 0;
1212 }
1213
1214 int bus_add_match_internal_kernel(
1215                 sd_bus *bus,
1216                 struct bus_match_component *components,
1217                 unsigned n_components,
1218                 uint64_t cookie) {
1219
1220         struct kdbus_cmd_match *m;
1221         struct kdbus_item *item;
1222         uint64_t *bloom;
1223         size_t sz;
1224         const char *sender = NULL;
1225         size_t sender_length = 0;
1226         uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
1227         bool using_bloom = false;
1228         unsigned i;
1229         bool matches_name_change = true;
1230         const char *name_change_arg[3] = {};
1231         int r;
1232
1233         assert(bus);
1234
1235         /* Monitor streams don't support matches, make this a NOP */
1236         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1237                 return 0;
1238
1239         bloom = alloca0(bus->bloom_size);
1240
1241         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1242
1243         for (i = 0; i < n_components; i++) {
1244                 struct bus_match_component *c = &components[i];
1245
1246                 switch (c->type) {
1247
1248                 case BUS_MATCH_SENDER:
1249                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1250                                 matches_name_change = false;
1251
1252                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1253                         if (r < 0)
1254                                 return r;
1255                         else if (r > 0)
1256                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1257                         else  {
1258                                 sender = c->value_str;
1259                                 sender_length = strlen(sender);
1260                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1261                         }
1262
1263                         break;
1264
1265                 case BUS_MATCH_MESSAGE_TYPE:
1266                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1267                                 matches_name_change = false;
1268
1269                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1270                         using_bloom = true;
1271                         break;
1272
1273                 case BUS_MATCH_INTERFACE:
1274                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1275                                 matches_name_change = false;
1276
1277                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1278                         using_bloom = true;
1279                         break;
1280
1281                 case BUS_MATCH_MEMBER:
1282                         if (!streq(c->value_str, "NameOwnerChanged"))
1283                                 matches_name_change = false;
1284
1285                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1286                         using_bloom = true;
1287                         break;
1288
1289                 case BUS_MATCH_PATH:
1290                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1291                                 matches_name_change = false;
1292
1293                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1294                         using_bloom = true;
1295                         break;
1296
1297                 case BUS_MATCH_PATH_NAMESPACE:
1298                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1299                         using_bloom = true;
1300                         break;
1301
1302                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1303                         char buf[sizeof("arg")-1 + 2 + 1];
1304
1305                         if (c->type - BUS_MATCH_ARG < 3)
1306                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1307
1308                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1309                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1310                         using_bloom = true;
1311                         break;
1312                 }
1313
1314                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1315                         /*
1316                          * XXX: DBus spec defines arg[0..63]path= matching to be
1317                          * a two-way glob. That is, if either string is a prefix
1318                          * of the other, it matches.
1319                          * This is really hard to realize in bloom-filters, as
1320                          * we would have to create a bloom-match for each prefix
1321                          * of @c->value_str. This is excessive, hence we just
1322                          * ignore all those matches and accept everything from
1323                          * the kernel. People should really avoid those matches.
1324                          * If they're used in real-life some day, we will have
1325                          * to properly support multiple-matches here.
1326                          */
1327                         break;
1328                 }
1329
1330                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1331                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1332
1333                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1334                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1335                         using_bloom = true;
1336                         break;
1337                 }
1338
1339                 case BUS_MATCH_DESTINATION: {
1340                         /*
1341                          * Kernel only supports matching on destination IDs, but
1342                          * not on destination names. So just skip the
1343                          * destination name restriction and verify it in
1344                          * user-space on retrieval.
1345                          */
1346                         r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
1347                         if (r < 0)
1348                                 return r;
1349                         else if (r > 0)
1350                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1351
1352                         /* if not a broadcast, it cannot be a name-change */
1353                         if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
1354                                 matches_name_change = false;
1355
1356                         break;
1357                 }
1358
1359                 case BUS_MATCH_ROOT:
1360                 case BUS_MATCH_VALUE:
1361                 case BUS_MATCH_LEAF:
1362                 case _BUS_MATCH_NODE_TYPE_MAX:
1363                 case _BUS_MATCH_NODE_TYPE_INVALID:
1364                         assert_not_reached("Invalid match type?");
1365                 }
1366         }
1367
1368         if (using_bloom)
1369                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1370
1371         m = alloca0_align(sz, 8);
1372         m->size = sz;
1373         m->cookie = cookie;
1374
1375         item = m->items;
1376
1377         if (src_id != KDBUS_MATCH_ID_ANY) {
1378                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1379                 item->type = KDBUS_ITEM_ID;
1380                 item->id = src_id;
1381                 item = KDBUS_ITEM_NEXT(item);
1382         }
1383
1384         if (dst_id != KDBUS_MATCH_ID_ANY) {
1385                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1386                 item->type = KDBUS_ITEM_DST_ID;
1387                 item->id = dst_id;
1388                 item = KDBUS_ITEM_NEXT(item);
1389         }
1390
1391         if (using_bloom) {
1392                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1393                 item->type = KDBUS_ITEM_BLOOM_MASK;
1394                 memcpy(item->data64, bloom, bus->bloom_size);
1395                 item = KDBUS_ITEM_NEXT(item);
1396         }
1397
1398         if (sender) {
1399                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1400                 item->type = KDBUS_ITEM_NAME;
1401                 memcpy(item->str, sender, sender_length + 1);
1402         }
1403
1404         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1405         if (r < 0)
1406                 return -errno;
1407
1408         if (matches_name_change) {
1409
1410                 /* If this match could theoretically match
1411                  * NameOwnerChanged messages, we need to
1412                  * install a second non-bloom filter explitly
1413                  * for it */
1414
1415                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1416                 if (r < 0)
1417                         return r;
1418         }
1419
1420         return 0;
1421 }
1422
1423 #define internal_match(bus, m)                                          \
1424         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1425          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1426          : (m))
1427
1428 static int bus_add_match_internal_dbus1(
1429                 sd_bus *bus,
1430                 const char *match) {
1431
1432         const char *e;
1433
1434         assert(bus);
1435         assert(match);
1436
1437         e = internal_match(bus, match);
1438
1439         return sd_bus_call_method(
1440                         bus,
1441                         "org.freedesktop.DBus",
1442                         "/org/freedesktop/DBus",
1443                         "org.freedesktop.DBus",
1444                         "AddMatch",
1445                         NULL,
1446                         NULL,
1447                         "s",
1448                         e);
1449 }
1450
1451 int bus_add_match_internal(
1452                 sd_bus *bus,
1453                 const char *match,
1454                 struct bus_match_component *components,
1455                 unsigned n_components,
1456                 uint64_t cookie) {
1457
1458         assert(bus);
1459
1460         if (!bus->bus_client)
1461                 return -EINVAL;
1462
1463         if (bus->is_kernel)
1464                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1465         else
1466                 return bus_add_match_internal_dbus1(bus, match);
1467 }
1468
1469 int bus_remove_match_internal_kernel(
1470                 sd_bus *bus,
1471                 uint64_t cookie) {
1472
1473         struct kdbus_cmd_match m = {
1474                 .size = offsetof(struct kdbus_cmd_match, items),
1475                 .cookie = cookie,
1476         };
1477         int r;
1478
1479         assert(bus);
1480
1481         /* Monitor streams don't support matches, make this a NOP */
1482         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1483                 return 0;
1484
1485         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1486         if (r < 0)
1487                 return -errno;
1488
1489         return 0;
1490 }
1491
1492 static int bus_remove_match_internal_dbus1(
1493                 sd_bus *bus,
1494                 const char *match) {
1495
1496         const char *e;
1497
1498         assert(bus);
1499         assert(match);
1500
1501         e = internal_match(bus, match);
1502
1503         return sd_bus_call_method(
1504                         bus,
1505                         "org.freedesktop.DBus",
1506                         "/org/freedesktop/DBus",
1507                         "org.freedesktop.DBus",
1508                         "RemoveMatch",
1509                         NULL,
1510                         NULL,
1511                         "s",
1512                         e);
1513 }
1514
1515 int bus_remove_match_internal(
1516                 sd_bus *bus,
1517                 const char *match,
1518                 uint64_t cookie) {
1519
1520         assert(bus);
1521
1522         if (!bus->bus_client)
1523                 return -EINVAL;
1524
1525         if (bus->is_kernel)
1526                 return bus_remove_match_internal_kernel(bus, cookie);
1527         else
1528                 return bus_remove_match_internal_dbus1(bus, match);
1529 }
1530
1531 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1532         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1533         const char *mid;
1534         int r;
1535
1536         assert_return(bus, -EINVAL);
1537         assert_return(name, -EINVAL);
1538         assert_return(machine, -EINVAL);
1539         assert_return(!bus_pid_changed(bus), -ECHILD);
1540         assert_return(service_name_is_valid(name), -EINVAL);
1541
1542         if (!bus->bus_client)
1543                 return -EINVAL;
1544
1545         if (!BUS_IS_OPEN(bus->state))
1546                 return -ENOTCONN;
1547
1548         if (streq_ptr(name, bus->unique_name))
1549                 return sd_id128_get_machine(machine);
1550
1551         r = sd_bus_message_new_method_call(
1552                         bus,
1553                         &m,
1554                         name,
1555                         "/",
1556                         "org.freedesktop.DBus.Peer",
1557                         "GetMachineId");
1558         if (r < 0)
1559                 return r;
1560
1561         r = sd_bus_message_set_auto_start(m, false);
1562         if (r < 0)
1563                 return r;
1564
1565         r = sd_bus_call(bus, m, 0, NULL, &reply);
1566         if (r < 0)
1567                 return r;
1568
1569         r = sd_bus_message_read(reply, "s", &mid);
1570         if (r < 0)
1571                 return r;
1572
1573         return sd_id128_from_string(mid, machine);
1574 }