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