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