chiark / gitweb /
11039033588be9488c3ac7526c002ac23473097d
[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;
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                         if (!streq(c->value_str, "/")) {
1295                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1296                                 using_bloom = true;
1297                         }
1298                         break;
1299
1300                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1301                         char buf[sizeof("arg")-1 + 2 + 1];
1302
1303                         if (c->type - BUS_MATCH_ARG < 3)
1304                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1305
1306                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1307                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1308                         using_bloom = true;
1309                         break;
1310                 }
1311
1312                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1313                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1314
1315                         xsprintf(buf, "arg%i-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1316                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1317                         using_bloom = true;
1318                         break;
1319                 }
1320
1321                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1322                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1323
1324                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1325                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1326                         using_bloom = true;
1327                         break;
1328                 }
1329
1330                 case BUS_MATCH_DESTINATION:
1331                         /* The bloom filter does not include
1332                            the destination, since it is only
1333                            available for broadcast messages
1334                            which do not carry a destination
1335                            since they are undirected. */
1336                         break;
1337
1338                 case BUS_MATCH_ROOT:
1339                 case BUS_MATCH_VALUE:
1340                 case BUS_MATCH_LEAF:
1341                 case _BUS_MATCH_NODE_TYPE_MAX:
1342                 case _BUS_MATCH_NODE_TYPE_INVALID:
1343                         assert_not_reached("Invalid match type?");
1344                 }
1345         }
1346
1347         if (using_bloom)
1348                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1349
1350         m = alloca0_align(sz, 8);
1351         m->size = sz;
1352         m->cookie = cookie;
1353
1354         item = m->items;
1355
1356         if (src_id != KDBUS_MATCH_ID_ANY) {
1357                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1358                 item->type = KDBUS_ITEM_ID;
1359                 item->id = src_id;
1360                 item = KDBUS_ITEM_NEXT(item);
1361         }
1362
1363         if (using_bloom) {
1364                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1365                 item->type = KDBUS_ITEM_BLOOM_MASK;
1366                 memcpy(item->data64, bloom, bus->bloom_size);
1367                 item = KDBUS_ITEM_NEXT(item);
1368         }
1369
1370         if (sender) {
1371                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1372                 item->type = KDBUS_ITEM_NAME;
1373                 memcpy(item->str, sender, sender_length + 1);
1374         }
1375
1376         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1377         if (r < 0)
1378                 return -errno;
1379
1380         if (matches_name_change) {
1381
1382                 /* If this match could theoretically match
1383                  * NameOwnerChanged messages, we need to
1384                  * install a second non-bloom filter explitly
1385                  * for it */
1386
1387                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1388                 if (r < 0)
1389                         return r;
1390         }
1391
1392         return 0;
1393 }
1394
1395 #define internal_match(bus, m)                                          \
1396         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1397          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1398          : (m))
1399
1400 static int bus_add_match_internal_dbus1(
1401                 sd_bus *bus,
1402                 const char *match) {
1403
1404         const char *e;
1405
1406         assert(bus);
1407         assert(match);
1408
1409         e = internal_match(bus, match);
1410
1411         return sd_bus_call_method(
1412                         bus,
1413                         "org.freedesktop.DBus",
1414                         "/org/freedesktop/DBus",
1415                         "org.freedesktop.DBus",
1416                         "AddMatch",
1417                         NULL,
1418                         NULL,
1419                         "s",
1420                         e);
1421 }
1422
1423 int bus_add_match_internal(
1424                 sd_bus *bus,
1425                 const char *match,
1426                 struct bus_match_component *components,
1427                 unsigned n_components,
1428                 uint64_t cookie) {
1429
1430         assert(bus);
1431
1432         if (!bus->bus_client)
1433                 return -EINVAL;
1434
1435         if (bus->is_kernel)
1436                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1437         else
1438                 return bus_add_match_internal_dbus1(bus, match);
1439 }
1440
1441 int bus_remove_match_internal_kernel(
1442                 sd_bus *bus,
1443                 uint64_t cookie) {
1444
1445         struct kdbus_cmd_match m = {
1446                 .size = offsetof(struct kdbus_cmd_match, items),
1447                 .cookie = cookie,
1448         };
1449         int r;
1450
1451         assert(bus);
1452
1453         /* Monitor streams don't support matches, make this a NOP */
1454         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1455                 return 0;
1456
1457         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1458         if (r < 0)
1459                 return -errno;
1460
1461         return 0;
1462 }
1463
1464 static int bus_remove_match_internal_dbus1(
1465                 sd_bus *bus,
1466                 const char *match) {
1467
1468         const char *e;
1469
1470         assert(bus);
1471         assert(match);
1472
1473         e = internal_match(bus, match);
1474
1475         return sd_bus_call_method(
1476                         bus,
1477                         "org.freedesktop.DBus",
1478                         "/org/freedesktop/DBus",
1479                         "org.freedesktop.DBus",
1480                         "RemoveMatch",
1481                         NULL,
1482                         NULL,
1483                         "s",
1484                         e);
1485 }
1486
1487 int bus_remove_match_internal(
1488                 sd_bus *bus,
1489                 const char *match,
1490                 uint64_t cookie) {
1491
1492         assert(bus);
1493
1494         if (!bus->bus_client)
1495                 return -EINVAL;
1496
1497         if (bus->is_kernel)
1498                 return bus_remove_match_internal_kernel(bus, cookie);
1499         else
1500                 return bus_remove_match_internal_dbus1(bus, match);
1501 }
1502
1503 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1504         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1505         const char *mid;
1506         int r;
1507
1508         assert_return(bus, -EINVAL);
1509         assert_return(name, -EINVAL);
1510         assert_return(machine, -EINVAL);
1511         assert_return(!bus_pid_changed(bus), -ECHILD);
1512         assert_return(service_name_is_valid(name), -EINVAL);
1513
1514         if (!bus->bus_client)
1515                 return -EINVAL;
1516
1517         if (!BUS_IS_OPEN(bus->state))
1518                 return -ENOTCONN;
1519
1520         if (streq_ptr(name, bus->unique_name))
1521                 return sd_id128_get_machine(machine);
1522
1523         r = sd_bus_message_new_method_call(
1524                         bus,
1525                         &m,
1526                         name,
1527                         "/",
1528                         "org.freedesktop.DBus.Peer",
1529                         "GetMachineId");
1530         if (r < 0)
1531                 return r;
1532
1533         r = sd_bus_message_set_auto_start(m, false);
1534         if (r < 0)
1535                 return r;
1536
1537         r = sd_bus_call(bus, m, 0, NULL, &reply);
1538         if (r < 0)
1539                 return r;
1540
1541         r = sd_bus_message_read(reply, "s", &mid);
1542         if (r < 0)
1543                 return r;
1544
1545         return sd_id128_from_string(mid, machine);
1546 }