chiark / gitweb /
a38c5c50fcaee7c654ebe1cbeadc85d0dd164dd6
[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
1191                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1192                         if (r < 0)
1193                                 return -errno;
1194                 }
1195
1196                 /* If thew new name is unset or empty, then this can
1197                  * match against removed ids */
1198                 if (!new_owner || new_owner[0] == 0) {
1199                         item->type = KDBUS_ITEM_ID_REMOVE;
1200
1201                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1202                         if (r < 0)
1203                                 return -errno;
1204                 }
1205         }
1206
1207         return 0;
1208 }
1209
1210 int bus_add_match_internal_kernel(
1211                 sd_bus *bus,
1212                 struct bus_match_component *components,
1213                 unsigned n_components,
1214                 uint64_t cookie) {
1215
1216         struct kdbus_cmd_match *m;
1217         struct kdbus_item *item;
1218         uint64_t *bloom;
1219         size_t sz;
1220         const char *sender = NULL;
1221         size_t sender_length = 0;
1222         uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
1223         bool using_bloom = false;
1224         unsigned i;
1225         bool matches_name_change = true;
1226         const char *name_change_arg[3] = {};
1227         int r;
1228
1229         assert(bus);
1230
1231         /* Monitor streams don't support matches, make this a NOP */
1232         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1233                 return 0;
1234
1235         bloom = alloca0(bus->bloom_size);
1236
1237         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1238
1239         for (i = 0; i < n_components; i++) {
1240                 struct bus_match_component *c = &components[i];
1241
1242                 switch (c->type) {
1243
1244                 case BUS_MATCH_SENDER:
1245                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1246                                 matches_name_change = false;
1247
1248                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1249                         if (r < 0)
1250                                 return r;
1251                         else if (r > 0)
1252                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1253                         else  {
1254                                 sender = c->value_str;
1255                                 sender_length = strlen(sender);
1256                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1257                         }
1258
1259                         break;
1260
1261                 case BUS_MATCH_MESSAGE_TYPE:
1262                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1263                                 matches_name_change = false;
1264
1265                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1266                         using_bloom = true;
1267                         break;
1268
1269                 case BUS_MATCH_INTERFACE:
1270                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1271                                 matches_name_change = false;
1272
1273                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1274                         using_bloom = true;
1275                         break;
1276
1277                 case BUS_MATCH_MEMBER:
1278                         if (!streq(c->value_str, "NameOwnerChanged"))
1279                                 matches_name_change = false;
1280
1281                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1282                         using_bloom = true;
1283                         break;
1284
1285                 case BUS_MATCH_PATH:
1286                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1287                                 matches_name_change = false;
1288
1289                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1290                         using_bloom = true;
1291                         break;
1292
1293                 case BUS_MATCH_PATH_NAMESPACE:
1294                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1295                         using_bloom = true;
1296                         break;
1297
1298                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1299                         char buf[sizeof("arg")-1 + 2 + 1];
1300
1301                         if (c->type - BUS_MATCH_ARG < 3)
1302                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1303
1304                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1305                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1306                         using_bloom = true;
1307                         break;
1308                 }
1309
1310                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1311                         /*
1312                          * XXX: DBus spec defines arg[0..63]path= matching to be
1313                          * a two-way glob. That is, if either string is a prefix
1314                          * of the other, it matches.
1315                          * This is really hard to realize in bloom-filters, as
1316                          * we would have to create a bloom-match for each prefix
1317                          * of @c->value_str. This is excessive, hence we just
1318                          * ignore all those matches and accept everything from
1319                          * the kernel. People should really avoid those matches.
1320                          * If they're used in real-life some day, we will have
1321                          * to properly support multiple-matches here.
1322                          */
1323                         break;
1324                 }
1325
1326                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1327                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1328
1329                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1330                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1331                         using_bloom = true;
1332                         break;
1333                 }
1334
1335                 case BUS_MATCH_DESTINATION: {
1336                         /*
1337                          * Kernel only supports matching on destination IDs, but
1338                          * not on destination names. So just skip the
1339                          * destination name restriction and verify it in
1340                          * user-space on retrieval.
1341                          */
1342                         r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
1343                         if (r < 0)
1344                                 return r;
1345                         else if (r > 0)
1346                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1347
1348                         break;
1349                 }
1350
1351                 case BUS_MATCH_ROOT:
1352                 case BUS_MATCH_VALUE:
1353                 case BUS_MATCH_LEAF:
1354                 case _BUS_MATCH_NODE_TYPE_MAX:
1355                 case _BUS_MATCH_NODE_TYPE_INVALID:
1356                         assert_not_reached("Invalid match type?");
1357                 }
1358         }
1359
1360         if (using_bloom)
1361                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1362
1363         m = alloca0_align(sz, 8);
1364         m->size = sz;
1365         m->cookie = cookie;
1366
1367         item = m->items;
1368
1369         if (src_id != KDBUS_MATCH_ID_ANY) {
1370                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1371                 item->type = KDBUS_ITEM_ID;
1372                 item->id = src_id;
1373                 item = KDBUS_ITEM_NEXT(item);
1374         }
1375
1376         if (dst_id != KDBUS_MATCH_ID_ANY) {
1377                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1378                 item->type = KDBUS_ITEM_DST_ID;
1379                 item->id = dst_id;
1380                 item = KDBUS_ITEM_NEXT(item);
1381         }
1382
1383         if (using_bloom) {
1384                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1385                 item->type = KDBUS_ITEM_BLOOM_MASK;
1386                 memcpy(item->data64, bloom, bus->bloom_size);
1387                 item = KDBUS_ITEM_NEXT(item);
1388         }
1389
1390         if (sender) {
1391                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1392                 item->type = KDBUS_ITEM_NAME;
1393                 memcpy(item->str, sender, sender_length + 1);
1394         }
1395
1396         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1397         if (r < 0)
1398                 return -errno;
1399
1400         if (matches_name_change) {
1401
1402                 /* If this match could theoretically match
1403                  * NameOwnerChanged messages, we need to
1404                  * install a second non-bloom filter explitly
1405                  * for it */
1406
1407                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1408                 if (r < 0)
1409                         return r;
1410         }
1411
1412         return 0;
1413 }
1414
1415 #define internal_match(bus, m)                                          \
1416         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1417          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1418          : (m))
1419
1420 static int bus_add_match_internal_dbus1(
1421                 sd_bus *bus,
1422                 const char *match) {
1423
1424         const char *e;
1425
1426         assert(bus);
1427         assert(match);
1428
1429         e = internal_match(bus, match);
1430
1431         return sd_bus_call_method(
1432                         bus,
1433                         "org.freedesktop.DBus",
1434                         "/org/freedesktop/DBus",
1435                         "org.freedesktop.DBus",
1436                         "AddMatch",
1437                         NULL,
1438                         NULL,
1439                         "s",
1440                         e);
1441 }
1442
1443 int bus_add_match_internal(
1444                 sd_bus *bus,
1445                 const char *match,
1446                 struct bus_match_component *components,
1447                 unsigned n_components,
1448                 uint64_t cookie) {
1449
1450         assert(bus);
1451
1452         if (!bus->bus_client)
1453                 return -EINVAL;
1454
1455         if (bus->is_kernel)
1456                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1457         else
1458                 return bus_add_match_internal_dbus1(bus, match);
1459 }
1460
1461 int bus_remove_match_internal_kernel(
1462                 sd_bus *bus,
1463                 uint64_t cookie) {
1464
1465         struct kdbus_cmd_match m = {
1466                 .size = offsetof(struct kdbus_cmd_match, items),
1467                 .cookie = cookie,
1468         };
1469         int r;
1470
1471         assert(bus);
1472
1473         /* Monitor streams don't support matches, make this a NOP */
1474         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1475                 return 0;
1476
1477         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1478         if (r < 0)
1479                 return -errno;
1480
1481         return 0;
1482 }
1483
1484 static int bus_remove_match_internal_dbus1(
1485                 sd_bus *bus,
1486                 const char *match) {
1487
1488         const char *e;
1489
1490         assert(bus);
1491         assert(match);
1492
1493         e = internal_match(bus, match);
1494
1495         return sd_bus_call_method(
1496                         bus,
1497                         "org.freedesktop.DBus",
1498                         "/org/freedesktop/DBus",
1499                         "org.freedesktop.DBus",
1500                         "RemoveMatch",
1501                         NULL,
1502                         NULL,
1503                         "s",
1504                         e);
1505 }
1506
1507 int bus_remove_match_internal(
1508                 sd_bus *bus,
1509                 const char *match,
1510                 uint64_t cookie) {
1511
1512         assert(bus);
1513
1514         if (!bus->bus_client)
1515                 return -EINVAL;
1516
1517         if (bus->is_kernel)
1518                 return bus_remove_match_internal_kernel(bus, cookie);
1519         else
1520                 return bus_remove_match_internal_dbus1(bus, match);
1521 }
1522
1523 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1524         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1525         const char *mid;
1526         int r;
1527
1528         assert_return(bus, -EINVAL);
1529         assert_return(name, -EINVAL);
1530         assert_return(machine, -EINVAL);
1531         assert_return(!bus_pid_changed(bus), -ECHILD);
1532         assert_return(service_name_is_valid(name), -EINVAL);
1533
1534         if (!bus->bus_client)
1535                 return -EINVAL;
1536
1537         if (!BUS_IS_OPEN(bus->state))
1538                 return -ENOTCONN;
1539
1540         if (streq_ptr(name, bus->unique_name))
1541                 return sd_id128_get_machine(machine);
1542
1543         r = sd_bus_message_new_method_call(
1544                         bus,
1545                         &m,
1546                         name,
1547                         "/",
1548                         "org.freedesktop.DBus.Peer",
1549                         "GetMachineId");
1550         if (r < 0)
1551                 return r;
1552
1553         r = sd_bus_message_set_auto_start(m, false);
1554         if (r < 0)
1555                 return r;
1556
1557         r = sd_bus_call(bus, m, 0, NULL, &reply);
1558         if (r < 0)
1559                 return r;
1560
1561         r = sd_bus_message_read(reply, "s", &mid);
1562         if (r < 0)
1563                 return r;
1564
1565         return sd_id128_from_string(mid, machine);
1566 }