]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-control.c
util-lib: split our string related calls from util.[ch] into its own file string...
[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 "sd-bus.h"
30
31 #include "bus-bloom.h"
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-util.h"
35 #include "capability.h"
36 #include "string-util.h"
37 #include "strv.h"
38 #include "bus-control.h"
39
40 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
41 int r;
42
43 assert_return(bus, -EINVAL);
44 assert_return(unique, -EINVAL);
45 assert_return(!bus_pid_changed(bus), -ECHILD);
46
47 if (!bus->bus_client)
48 return -EINVAL;
49
50 r = bus_ensure_running(bus);
51 if (r < 0)
52 return r;
53
54 *unique = bus->unique_name;
55 return 0;
56 }
57
58 static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
59 struct kdbus_cmd *n;
60 size_t size, l;
61 int r;
62
63 assert(bus);
64 assert(name);
65
66 l = strlen(name) + 1;
67 size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
68 n = alloca0_align(size, 8);
69 n->size = size;
70 n->flags = request_name_flags_to_kdbus(flags);
71
72 n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
73 n->items[0].type = KDBUS_ITEM_NAME;
74 memcpy(n->items[0].str, name, l);
75
76 #ifdef HAVE_VALGRIND_MEMCHECK_H
77 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
78 #endif
79
80 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
81 if (r < 0)
82 return -errno;
83
84 if (n->return_flags & KDBUS_NAME_IN_QUEUE)
85 return 0;
86
87 return 1;
88 }
89
90 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
91 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
92 uint32_t ret, param = 0;
93 int r;
94
95 assert(bus);
96 assert(name);
97
98 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
99 param |= BUS_NAME_ALLOW_REPLACEMENT;
100 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
101 param |= BUS_NAME_REPLACE_EXISTING;
102 if (!(flags & SD_BUS_NAME_QUEUE))
103 param |= BUS_NAME_DO_NOT_QUEUE;
104
105 r = sd_bus_call_method(
106 bus,
107 "org.freedesktop.DBus",
108 "/org/freedesktop/DBus",
109 "org.freedesktop.DBus",
110 "RequestName",
111 NULL,
112 &reply,
113 "su",
114 name,
115 param);
116 if (r < 0)
117 return r;
118
119 r = sd_bus_message_read(reply, "u", &ret);
120 if (r < 0)
121 return r;
122
123 if (ret == BUS_NAME_ALREADY_OWNER)
124 return -EALREADY;
125 else if (ret == BUS_NAME_EXISTS)
126 return -EEXIST;
127 else if (ret == BUS_NAME_IN_QUEUE)
128 return 0;
129 else if (ret == BUS_NAME_PRIMARY_OWNER)
130 return 1;
131
132 return -EIO;
133 }
134
135 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
136 assert_return(bus, -EINVAL);
137 assert_return(name, -EINVAL);
138 assert_return(!bus_pid_changed(bus), -ECHILD);
139 assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
140 assert_return(service_name_is_valid(name), -EINVAL);
141 assert_return(name[0] != ':', -EINVAL);
142
143 if (!bus->bus_client)
144 return -EINVAL;
145
146 /* Don't allow requesting the special driver and local names */
147 if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
148 return -EINVAL;
149
150 if (!BUS_IS_OPEN(bus->state))
151 return -ENOTCONN;
152
153 if (bus->is_kernel)
154 return bus_request_name_kernel(bus, name, flags);
155 else
156 return bus_request_name_dbus1(bus, name, flags);
157 }
158
159 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
160 struct kdbus_cmd *n;
161 size_t size, l;
162 int r;
163
164 assert(bus);
165 assert(name);
166
167 l = strlen(name) + 1;
168 size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
169 n = alloca0_align(size, 8);
170 n->size = size;
171
172 n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
173 n->items[0].type = KDBUS_ITEM_NAME;
174 memcpy(n->items[0].str, name, l);
175
176 #ifdef HAVE_VALGRIND_MEMCHECK_H
177 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
178 #endif
179 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
180 if (r < 0)
181 return -errno;
182
183 return 0;
184 }
185
186 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
187 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
188 uint32_t ret;
189 int r;
190
191 assert(bus);
192 assert(name);
193
194 r = sd_bus_call_method(
195 bus,
196 "org.freedesktop.DBus",
197 "/org/freedesktop/DBus",
198 "org.freedesktop.DBus",
199 "ReleaseName",
200 NULL,
201 &reply,
202 "s",
203 name);
204 if (r < 0)
205 return r;
206
207 r = sd_bus_message_read(reply, "u", &ret);
208 if (r < 0)
209 return r;
210 if (ret == BUS_NAME_NON_EXISTENT)
211 return -ESRCH;
212 if (ret == BUS_NAME_NOT_OWNER)
213 return -EADDRINUSE;
214 if (ret == BUS_NAME_RELEASED)
215 return 0;
216
217 return -EINVAL;
218 }
219
220 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
221 assert_return(bus, -EINVAL);
222 assert_return(name, -EINVAL);
223 assert_return(!bus_pid_changed(bus), -ECHILD);
224 assert_return(service_name_is_valid(name), -EINVAL);
225 assert_return(name[0] != ':', -EINVAL);
226
227 if (!bus->bus_client)
228 return -EINVAL;
229
230 /* Don't allow releasing the special driver and local names */
231 if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
232 return -EINVAL;
233
234 if (!BUS_IS_OPEN(bus->state))
235 return -ENOTCONN;
236
237 if (bus->is_kernel)
238 return bus_release_name_kernel(bus, name);
239 else
240 return bus_release_name_dbus1(bus, name);
241 }
242
243 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
244 struct kdbus_cmd_list cmd = {
245 .size = sizeof(cmd),
246 .flags = flags,
247 };
248 struct kdbus_info *name_list, *name;
249 uint64_t previous_id = 0;
250 int r;
251
252 /* Caller will free half-constructed list on failure... */
253
254 r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
255 if (r < 0)
256 return -errno;
257
258 name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
259
260 KDBUS_FOREACH(name, name_list, cmd.list_size) {
261 struct kdbus_item *item;
262
263 if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) {
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 if (service_name_is_valid(item->name.name)) {
281 r = strv_extend(x, item->name.name);
282 if (r < 0) {
283 r = -ENOMEM;
284 goto fail;
285 }
286 }
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 (isempty(old_owner)) {
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 (isempty(new_owner)) {
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 (isempty(old_owner)) {
1189 item->type = KDBUS_ITEM_ID_ADD;
1190 if (!isempty(new_owner))
1191 item->id_change.id = new_owner_id;
1192
1193 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1194 if (r < 0)
1195 return -errno;
1196 }
1197
1198 /* If thew new name is unset or empty, then this can
1199 * match against removed ids */
1200 if (isempty(new_owner)) {
1201 item->type = KDBUS_ITEM_ID_REMOVE;
1202 if (!isempty(old_owner))
1203 item->id_change.id = old_owner_id;
1204
1205 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1206 if (r < 0)
1207 return -errno;
1208 }
1209 }
1210
1211 return 0;
1212 }
1213
1214 int bus_add_match_internal_kernel(
1215 sd_bus *bus,
1216 struct bus_match_component *components,
1217 unsigned n_components,
1218 uint64_t cookie) {
1219
1220 struct kdbus_cmd_match *m;
1221 struct kdbus_item *item;
1222 uint64_t *bloom;
1223 size_t sz;
1224 const char *sender = NULL;
1225 size_t sender_length = 0;
1226 uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
1227 bool using_bloom = false;
1228 unsigned i;
1229 bool matches_name_change = true;
1230 const char *name_change_arg[3] = {};
1231 int r;
1232
1233 assert(bus);
1234
1235 /* Monitor streams don't support matches, make this a NOP */
1236 if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1237 return 0;
1238
1239 bloom = alloca0(bus->bloom_size);
1240
1241 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1242
1243 for (i = 0; i < n_components; i++) {
1244 struct bus_match_component *c = &components[i];
1245
1246 switch (c->type) {
1247
1248 case BUS_MATCH_SENDER:
1249 if (!streq(c->value_str, "org.freedesktop.DBus"))
1250 matches_name_change = false;
1251
1252 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1253 if (r < 0)
1254 return r;
1255 else if (r > 0)
1256 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1257 else {
1258 sender = c->value_str;
1259 sender_length = strlen(sender);
1260 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1261 }
1262
1263 break;
1264
1265 case BUS_MATCH_MESSAGE_TYPE:
1266 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1267 matches_name_change = false;
1268
1269 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1270 using_bloom = true;
1271 break;
1272
1273 case BUS_MATCH_INTERFACE:
1274 if (!streq(c->value_str, "org.freedesktop.DBus"))
1275 matches_name_change = false;
1276
1277 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1278 using_bloom = true;
1279 break;
1280
1281 case BUS_MATCH_MEMBER:
1282 if (!streq(c->value_str, "NameOwnerChanged"))
1283 matches_name_change = false;
1284
1285 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1286 using_bloom = true;
1287 break;
1288
1289 case BUS_MATCH_PATH:
1290 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1291 matches_name_change = false;
1292
1293 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1294 using_bloom = true;
1295 break;
1296
1297 case BUS_MATCH_PATH_NAMESPACE:
1298 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1299 using_bloom = true;
1300 break;
1301
1302 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1303 char buf[sizeof("arg")-1 + 2 + 1];
1304
1305 if (c->type - BUS_MATCH_ARG < 3)
1306 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1307
1308 xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1309 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1310 using_bloom = true;
1311 break;
1312 }
1313
1314 case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
1315 char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
1316
1317 xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
1318 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1319 using_bloom = true;
1320 break;
1321 }
1322
1323 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
1324 /*
1325 * XXX: DBus spec defines arg[0..63]path= matching to be
1326 * a two-way glob. That is, if either string is a prefix
1327 * of the other, it matches.
1328 * This is really hard to realize in bloom-filters, as
1329 * we would have to create a bloom-match for each prefix
1330 * of @c->value_str. This is excessive, hence we just
1331 * ignore all those matches and accept everything from
1332 * the kernel. People should really avoid those matches.
1333 * If they're used in real-life some day, we will have
1334 * to properly support multiple-matches here.
1335 */
1336 break;
1337
1338 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1339 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1340
1341 xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1342 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1343 using_bloom = true;
1344 break;
1345 }
1346
1347 case BUS_MATCH_DESTINATION:
1348 /*
1349 * Kernel only supports matching on destination IDs, but
1350 * not on destination names. So just skip the
1351 * destination name restriction and verify it in
1352 * user-space on retrieval.
1353 */
1354 r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
1355 if (r < 0)
1356 return r;
1357 else if (r > 0)
1358 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1359
1360 /* if not a broadcast, it cannot be a name-change */
1361 if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
1362 matches_name_change = false;
1363
1364 break;
1365
1366 case BUS_MATCH_ROOT:
1367 case BUS_MATCH_VALUE:
1368 case BUS_MATCH_LEAF:
1369 case _BUS_MATCH_NODE_TYPE_MAX:
1370 case _BUS_MATCH_NODE_TYPE_INVALID:
1371 assert_not_reached("Invalid match type?");
1372 }
1373 }
1374
1375 if (using_bloom)
1376 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1377
1378 m = alloca0_align(sz, 8);
1379 m->size = sz;
1380 m->cookie = cookie;
1381
1382 item = m->items;
1383
1384 if (src_id != KDBUS_MATCH_ID_ANY) {
1385 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1386 item->type = KDBUS_ITEM_ID;
1387 item->id = src_id;
1388 item = KDBUS_ITEM_NEXT(item);
1389 }
1390
1391 if (dst_id != KDBUS_MATCH_ID_ANY) {
1392 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1393 item->type = KDBUS_ITEM_DST_ID;
1394 item->id = dst_id;
1395 item = KDBUS_ITEM_NEXT(item);
1396 }
1397
1398 if (using_bloom) {
1399 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1400 item->type = KDBUS_ITEM_BLOOM_MASK;
1401 memcpy(item->data64, bloom, bus->bloom_size);
1402 item = KDBUS_ITEM_NEXT(item);
1403 }
1404
1405 if (sender) {
1406 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1407 item->type = KDBUS_ITEM_NAME;
1408 memcpy(item->str, sender, sender_length + 1);
1409 }
1410
1411 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1412 if (r < 0)
1413 return -errno;
1414
1415 if (matches_name_change) {
1416
1417 /* If this match could theoretically match
1418 * NameOwnerChanged messages, we need to
1419 * install a second non-bloom filter explitly
1420 * for it */
1421
1422 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1423 if (r < 0)
1424 return r;
1425 }
1426
1427 return 0;
1428 }
1429
1430 #define internal_match(bus, m) \
1431 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1432 ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1433 : (m))
1434
1435 static int bus_add_match_internal_dbus1(
1436 sd_bus *bus,
1437 const char *match) {
1438
1439 const char *e;
1440
1441 assert(bus);
1442 assert(match);
1443
1444 e = internal_match(bus, match);
1445
1446 return sd_bus_call_method(
1447 bus,
1448 "org.freedesktop.DBus",
1449 "/org/freedesktop/DBus",
1450 "org.freedesktop.DBus",
1451 "AddMatch",
1452 NULL,
1453 NULL,
1454 "s",
1455 e);
1456 }
1457
1458 int bus_add_match_internal(
1459 sd_bus *bus,
1460 const char *match,
1461 struct bus_match_component *components,
1462 unsigned n_components,
1463 uint64_t cookie) {
1464
1465 assert(bus);
1466
1467 if (!bus->bus_client)
1468 return -EINVAL;
1469
1470 if (bus->is_kernel)
1471 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1472 else
1473 return bus_add_match_internal_dbus1(bus, match);
1474 }
1475
1476 int bus_remove_match_internal_kernel(
1477 sd_bus *bus,
1478 uint64_t cookie) {
1479
1480 struct kdbus_cmd_match m = {
1481 .size = offsetof(struct kdbus_cmd_match, items),
1482 .cookie = cookie,
1483 };
1484 int r;
1485
1486 assert(bus);
1487
1488 /* Monitor streams don't support matches, make this a NOP */
1489 if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1490 return 0;
1491
1492 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1493 if (r < 0)
1494 return -errno;
1495
1496 return 0;
1497 }
1498
1499 static int bus_remove_match_internal_dbus1(
1500 sd_bus *bus,
1501 const char *match) {
1502
1503 const char *e;
1504
1505 assert(bus);
1506 assert(match);
1507
1508 e = internal_match(bus, match);
1509
1510 return sd_bus_call_method(
1511 bus,
1512 "org.freedesktop.DBus",
1513 "/org/freedesktop/DBus",
1514 "org.freedesktop.DBus",
1515 "RemoveMatch",
1516 NULL,
1517 NULL,
1518 "s",
1519 e);
1520 }
1521
1522 int bus_remove_match_internal(
1523 sd_bus *bus,
1524 const char *match,
1525 uint64_t cookie) {
1526
1527 assert(bus);
1528
1529 if (!bus->bus_client)
1530 return -EINVAL;
1531
1532 if (bus->is_kernel)
1533 return bus_remove_match_internal_kernel(bus, cookie);
1534 else
1535 return bus_remove_match_internal_dbus1(bus, match);
1536 }
1537
1538 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1539 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1540 const char *mid;
1541 int r;
1542
1543 assert_return(bus, -EINVAL);
1544 assert_return(name, -EINVAL);
1545 assert_return(machine, -EINVAL);
1546 assert_return(!bus_pid_changed(bus), -ECHILD);
1547 assert_return(service_name_is_valid(name), -EINVAL);
1548
1549 if (!bus->bus_client)
1550 return -EINVAL;
1551
1552 if (!BUS_IS_OPEN(bus->state))
1553 return -ENOTCONN;
1554
1555 if (streq_ptr(name, bus->unique_name))
1556 return sd_id128_get_machine(machine);
1557
1558 r = sd_bus_message_new_method_call(
1559 bus,
1560 &m,
1561 name,
1562 "/",
1563 "org.freedesktop.DBus.Peer",
1564 "GetMachineId");
1565 if (r < 0)
1566 return r;
1567
1568 r = sd_bus_message_set_auto_start(m, false);
1569 if (r < 0)
1570 return r;
1571
1572 r = sd_bus_call(bus, m, 0, NULL, &reply);
1573 if (r < 0)
1574 return r;
1575
1576 r = sd_bus_message_read(reply, "s", &mid);
1577 if (r < 0)
1578 return r;
1579
1580 return sd_id128_from_string(mid, machine);
1581 }