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