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