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