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