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