chiark / gitweb /
sd-bus: when bus operations are to be executed on direct connections always fail
[elogind.git] / src / libelogind / 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 && item->pids.ppid > 0) {
427                                 c->ppid = (pid_t) item->pids.ppid;
428                                 c->mask |= SD_BUS_CREDS_PPID;
429                         }
430
431                         break;
432
433                 case KDBUS_ITEM_CREDS:
434
435                         if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
436                                 c->uid = (uid_t) item->creds.uid;
437                                 c->mask |= SD_BUS_CREDS_UID;
438                         }
439
440                         if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
441                                 c->euid = (uid_t) item->creds.euid;
442                                 c->mask |= SD_BUS_CREDS_EUID;
443                         }
444
445                         if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
446                                 c->suid = (uid_t) item->creds.suid;
447                                 c->mask |= SD_BUS_CREDS_SUID;
448                         }
449
450                         if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
451                                 c->fsuid = (uid_t) item->creds.fsuid;
452                                 c->mask |= SD_BUS_CREDS_FSUID;
453                         }
454
455                         if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
456                                 c->gid = (gid_t) item->creds.gid;
457                                 c->mask |= SD_BUS_CREDS_GID;
458                         }
459
460                         if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
461                                 c->egid = (gid_t) item->creds.egid;
462                                 c->mask |= SD_BUS_CREDS_EGID;
463                         }
464
465                         if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
466                                 c->sgid = (gid_t) item->creds.sgid;
467                                 c->mask |= SD_BUS_CREDS_SGID;
468                         }
469
470                         if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
471                                 c->fsgid = (gid_t) item->creds.fsgid;
472                                 c->mask |= SD_BUS_CREDS_FSGID;
473                         }
474
475                         break;
476
477                 case KDBUS_ITEM_PID_COMM:
478                         if (mask & SD_BUS_CREDS_COMM) {
479                                 r = free_and_strdup(&c->comm, item->str);
480                                 if (r < 0)
481                                         return r;
482
483                                 c->mask |= SD_BUS_CREDS_COMM;
484                         }
485                         break;
486
487                 case KDBUS_ITEM_TID_COMM:
488                         if (mask & SD_BUS_CREDS_TID_COMM) {
489                                 r = free_and_strdup(&c->tid_comm, item->str);
490                                 if (r < 0)
491                                         return r;
492
493                                 c->mask |= SD_BUS_CREDS_TID_COMM;
494                         }
495                         break;
496
497                 case KDBUS_ITEM_EXE:
498                         if (mask & SD_BUS_CREDS_EXE) {
499                                 r = free_and_strdup(&c->exe, item->str);
500                                 if (r < 0)
501                                         return r;
502
503                                 c->mask |= SD_BUS_CREDS_EXE;
504                         }
505                         break;
506
507                 case KDBUS_ITEM_CMDLINE:
508                         if (mask & SD_BUS_CREDS_CMDLINE) {
509                                 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
510                                 c->cmdline = memdup(item->data, c->cmdline_size);
511                                 if (!c->cmdline)
512                                         return -ENOMEM;
513
514                                 c->mask |= SD_BUS_CREDS_CMDLINE;
515                         }
516                         break;
517
518                 case KDBUS_ITEM_CGROUP:
519                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
520                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
521                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
522
523                         if (m) {
524                                 r = free_and_strdup(&c->cgroup, item->str);
525                                 if (r < 0)
526                                         return r;
527
528                                 r = bus_get_root_path(bus);
529                                 if (r < 0)
530                                         return r;
531
532                                 r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
533                                 if (r < 0)
534                                         return r;
535
536                                 c->mask |= m;
537                         }
538                         break;
539
540                 case KDBUS_ITEM_CAPS:
541                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
542                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
543
544                         if (m) {
545                                 if (item->caps.last_cap != cap_last_cap() ||
546                                     item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
547                                         return -EBADMSG;
548
549                                 c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
550                                 if (!c->capability)
551                                         return -ENOMEM;
552
553                                 c->mask |= m;
554                         }
555                         break;
556
557                 case KDBUS_ITEM_SECLABEL:
558                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
559                                 r = free_and_strdup(&c->label, item->str);
560                                 if (r < 0)
561                                         return r;
562
563                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
564                         }
565                         break;
566
567                 case KDBUS_ITEM_AUDIT:
568                         if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID && (uint32_t) item->audit.sessionid != (uint32_t) -1) {
569                                 c->audit_session_id = (uint32_t) item->audit.sessionid;
570                                 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
571                         }
572
573                         if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID && (uid_t) item->audit.loginuid != UID_INVALID) {
574                                 c->audit_login_uid = (uid_t) item->audit.loginuid;
575                                 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
576                         }
577                         break;
578
579                 case KDBUS_ITEM_OWNED_NAME:
580                         if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
581                                 r = strv_extend(&c->well_known_names, item->name.name);
582                                 if (r < 0)
583                                         return r;
584
585                                 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
586                         }
587                         break;
588
589                 case KDBUS_ITEM_CONN_DESCRIPTION:
590                         if (mask & SD_BUS_CREDS_DESCRIPTION) {
591                                 r = free_and_strdup(&c->description, item->str);
592                                 if (r < 0)
593                                         return r;
594
595                                 c->mask |= SD_BUS_CREDS_DESCRIPTION;
596                         }
597                         break;
598
599                 case KDBUS_ITEM_AUXGROUPS:
600                         if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
601                                 size_t i, n;
602                                 uid_t *g;
603
604                                 n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
605                                 g = new(gid_t, n);
606                                 if (!g)
607                                         return -ENOMEM;
608
609                                 for (i = 0; i < n; i++)
610                                         g[i] = item->data64[i];
611
612                                 free(c->supplementary_gids);
613                                 c->supplementary_gids = g;
614                                 c->n_supplementary_gids = n;
615
616                                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
617                         }
618                         break;
619                 }
620         }
621
622         return 0;
623 }
624
625 int bus_get_name_creds_kdbus(
626                 sd_bus *bus,
627                 const char *name,
628                 uint64_t mask,
629                 bool allow_activator,
630                 sd_bus_creds **creds) {
631
632         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
633         struct kdbus_cmd_info *cmd;
634         struct kdbus_info *conn_info;
635         size_t size, l;
636         uint64_t id;
637         int r;
638
639         if (streq(name, "org.freedesktop.DBus"))
640                 return -EOPNOTSUPP;
641
642         r = bus_kernel_parse_unique_name(name, &id);
643         if (r < 0)
644                 return r;
645         if (r > 0) {
646                 size = offsetof(struct kdbus_cmd_info, items);
647                 cmd = alloca0_align(size, 8);
648                 cmd->id = id;
649         } else {
650                 l = strlen(name) + 1;
651                 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
652                 cmd = alloca0_align(size, 8);
653                 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
654                 cmd->items[0].type = KDBUS_ITEM_NAME;
655                 memcpy(cmd->items[0].str, name, l);
656         }
657
658         /* If augmentation is on, and the bus didn't provide us
659          * the bits we want, then ask for the PID/TID so that we
660          * can read the rest from /proc. */
661         if ((mask & SD_BUS_CREDS_AUGMENT) &&
662             (mask & (SD_BUS_CREDS_PPID|
663                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
664                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
665                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
666                      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|
667                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
668                      SD_BUS_CREDS_SELINUX_CONTEXT|
669                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
670                 mask |= SD_BUS_CREDS_PID;
671
672         cmd->size = size;
673         cmd->attach_flags = attach_flags_to_kdbus(mask);
674
675         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
676         if (r < 0)
677                 return -errno;
678
679         conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
680
681         /* Non-activated names are considered not available */
682         if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
683                 if (name[0] == ':')
684                         r = -ENXIO;
685                 else
686                         r = -ESRCH;
687                 goto fail;
688         }
689
690         c = bus_creds_new();
691         if (!c) {
692                 r = -ENOMEM;
693                 goto fail;
694         }
695
696         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
697                 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
698                         r = -ENOMEM;
699                         goto fail;
700                 }
701
702                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
703         }
704
705         /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
706            them in case the service has no names. This does not mean
707            however that the list of owned names could not be
708            acquired. Hence, let's explicitly clarify that the data is
709            complete. */
710         c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
711
712         r = bus_populate_creds_from_items(bus, conn_info, mask, c);
713         if (r < 0)
714                 goto fail;
715
716         r = bus_creds_add_more(c, mask, 0, 0);
717         if (r < 0)
718                 goto fail;
719
720         if (creds) {
721                 *creds = c;
722                 c = NULL;
723         }
724
725         r = 0;
726
727 fail:
728         bus_kernel_cmd_free(bus, cmd->offset);
729         return r;
730 }
731
732 static int bus_get_name_creds_dbus1(
733                 sd_bus *bus,
734                 const char *name,
735                 uint64_t mask,
736                 sd_bus_creds **creds) {
737
738         _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
739         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
740         const char *unique = NULL;
741         pid_t pid = 0;
742         int r;
743
744         /* Only query the owner if the caller wants to know it or if
745          * the caller just wants to check whether a name exists */
746         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
747                 r = sd_bus_call_method(
748                                 bus,
749                                 "org.freedesktop.DBus",
750                                 "/org/freedesktop/DBus",
751                                 "org.freedesktop.DBus",
752                                 "GetNameOwner",
753                                 NULL,
754                                 &reply_unique,
755                                 "s",
756                                 name);
757                 if (r < 0)
758                         return r;
759
760                 r = sd_bus_message_read(reply_unique, "s", &unique);
761                 if (r < 0)
762                         return r;
763         }
764
765         if (mask != 0) {
766                 c = bus_creds_new();
767                 if (!c)
768                         return -ENOMEM;
769
770                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
771                         c->unique_name = strdup(unique);
772                         if (!c->unique_name)
773                                 return -ENOMEM;
774
775                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
776                 }
777
778                 if ((mask & SD_BUS_CREDS_PID) ||
779                     ((mask & SD_BUS_CREDS_AUGMENT) &&
780                      (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
781                               SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
782                               SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
783                               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|
784                               SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
785                               SD_BUS_CREDS_SELINUX_CONTEXT|
786                               SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
787
788                         uint32_t u;
789
790                         r = sd_bus_call_method(
791                                         bus,
792                                         "org.freedesktop.DBus",
793                                         "/org/freedesktop/DBus",
794                                         "org.freedesktop.DBus",
795                                         "GetConnectionUnixProcessID",
796                                         NULL,
797                                         &reply,
798                                         "s",
799                                         unique ? unique : name);
800                         if (r < 0)
801                                 return r;
802
803                         r = sd_bus_message_read(reply, "u", &u);
804                         if (r < 0)
805                                 return r;
806
807                         pid = u;
808                         if (mask & SD_BUS_CREDS_PID) {
809                                 c->pid = u;
810                                 c->mask |= SD_BUS_CREDS_PID;
811                         }
812
813                         reply = sd_bus_message_unref(reply);
814                 }
815
816                 if (mask & SD_BUS_CREDS_EUID) {
817                         uint32_t u;
818
819                         r = sd_bus_call_method(
820                                         bus,
821                                         "org.freedesktop.DBus",
822                                         "/org/freedesktop/DBus",
823                                         "org.freedesktop.DBus",
824                                         "GetConnectionUnixUser",
825                                         NULL,
826                                         &reply,
827                                         "s",
828                                         unique ? unique : name);
829                         if (r < 0)
830                                 return r;
831
832                         r = sd_bus_message_read(reply, "u", &u);
833                         if (r < 0)
834                                 return r;
835
836                         c->euid = u;
837                         c->mask |= SD_BUS_CREDS_EUID;
838
839                         reply = sd_bus_message_unref(reply);
840                 }
841
842                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
843                         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
844                         const void *p = NULL;
845                         size_t sz = 0;
846
847                         r = sd_bus_call_method(
848                                         bus,
849                                         "org.freedesktop.DBus",
850                                         "/org/freedesktop/DBus",
851                                         "org.freedesktop.DBus",
852                                         "GetConnectionSELinuxSecurityContext",
853                                         &error,
854                                         &reply,
855                                         "s",
856                                         unique ? unique : name);
857                         if (r < 0) {
858                                 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
859                                         return r;
860                         } else {
861                                 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
862                                 if (r < 0)
863                                         return r;
864
865                                 c->label = strndup(p, sz);
866                                 if (!c->label)
867                                         return -ENOMEM;
868
869                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
870                         }
871                 }
872
873                 r = bus_creds_add_more(c, mask, pid, 0);
874                 if (r < 0)
875                         return r;
876         }
877
878         if (creds) {
879                 *creds = c;
880                 c = NULL;
881         }
882
883         return 0;
884 }
885
886 _public_ int sd_bus_get_name_creds(
887                 sd_bus *bus,
888                 const char *name,
889                 uint64_t mask,
890                 sd_bus_creds **creds) {
891
892         assert_return(bus, -EINVAL);
893         assert_return(name, -EINVAL);
894         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
895         assert_return(mask == 0 || creds, -EINVAL);
896         assert_return(!bus_pid_changed(bus), -ECHILD);
897         assert_return(service_name_is_valid(name), -EINVAL);
898
899         if (!bus->bus_client)
900                 return -EINVAL;
901
902         if (streq(name, "org.freedesktop.DBus.Local"))
903                 return -EINVAL;
904
905         if (!BUS_IS_OPEN(bus->state))
906                 return -ENOTCONN;
907
908         if (bus->is_kernel)
909                 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
910         else
911                 return bus_get_name_creds_dbus1(bus, name, mask, creds);
912 }
913
914 static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
915         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
916         struct kdbus_cmd_info cmd = {
917                 .size = sizeof(struct kdbus_cmd_info),
918         };
919         struct kdbus_info *creator_info;
920         pid_t pid = 0;
921         int r;
922
923         c = bus_creds_new();
924         if (!c)
925                 return -ENOMEM;
926
927         /* If augmentation is on, and the bus doesn't didn't allow us
928          * to get the bits we want, then ask for the PID/TID so that we
929          * can read the rest from /proc. */
930         if ((mask & SD_BUS_CREDS_AUGMENT) &&
931             (mask & (SD_BUS_CREDS_PPID|
932                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
933                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
934                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
935                      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|
936                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
937                      SD_BUS_CREDS_SELINUX_CONTEXT|
938                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
939                 mask |= SD_BUS_CREDS_PID;
940
941         cmd.attach_flags = attach_flags_to_kdbus(mask);
942
943         r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
944         if (r < 0)
945                 return -errno;
946
947         creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
948
949         r = bus_populate_creds_from_items(bus, creator_info, mask, c);
950         bus_kernel_cmd_free(bus, cmd.offset);
951         if (r < 0)
952                 return r;
953
954         r = bus_creds_add_more(c, mask, pid, 0);
955         if (r < 0)
956                 return r;
957
958         *ret = c;
959         c = NULL;
960         return 0;
961 }
962
963 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
964         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
965         pid_t pid = 0;
966         int r;
967
968         if (!bus->ucred_valid && !isempty(bus->label))
969                 return -ENODATA;
970
971         c = bus_creds_new();
972         if (!c)
973                 return -ENOMEM;
974
975         if (bus->ucred_valid) {
976                 if (bus->ucred.pid > 0) {
977                         pid = c->pid = bus->ucred.pid;
978                         c->mask |= SD_BUS_CREDS_PID & mask;
979                 }
980
981                 if (bus->ucred.uid != UID_INVALID) {
982                         c->euid = bus->ucred.uid;
983                         c->mask |= SD_BUS_CREDS_EUID & mask;
984                 }
985
986                 if (bus->ucred.gid != GID_INVALID) {
987                         c->egid = bus->ucred.gid;
988                         c->mask |= SD_BUS_CREDS_EGID & mask;
989                 }
990         }
991
992         if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
993                 c->label = strdup(bus->label);
994                 if (!c->label)
995                         return -ENOMEM;
996
997                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
998         }
999
1000         r = bus_creds_add_more(c, mask, pid, 0);
1001         if (r < 0)
1002                 return r;
1003
1004         *ret = c;
1005         c = NULL;
1006         return 0;
1007 }
1008
1009 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
1010         assert_return(bus, -EINVAL);
1011         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
1012         assert_return(ret, -EINVAL);
1013         assert_return(!bus_pid_changed(bus), -ECHILD);
1014
1015         if (!BUS_IS_OPEN(bus->state))
1016                 return -ENOTCONN;
1017
1018         if (bus->is_kernel)
1019                 return bus_get_owner_creds_kdbus(bus, mask, ret);
1020         else
1021                 return bus_get_owner_creds_dbus1(bus, mask, ret);
1022 }
1023
1024 static int add_name_change_match(sd_bus *bus,
1025                                  uint64_t cookie,
1026                                  const char *name,
1027                                  const char *old_owner,
1028                                  const char *new_owner) {
1029
1030         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
1031         int is_name_id = -1, r;
1032         struct kdbus_item *item;
1033
1034         assert(bus);
1035
1036         /* If we encounter a match that could match against
1037          * NameOwnerChanged messages, then we need to create
1038          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1039          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1040          * multiple if the match is underspecified.
1041          *
1042          * The NameOwnerChanged signals take three parameters with
1043          * unique or well-known names, but only some forms actually
1044          * exist:
1045          *
1046          * WELLKNOWN, "", UNIQUE       â†’ KDBUS_ITEM_NAME_ADD
1047          * WELLKNOWN, UNIQUE, ""       â†’ KDBUS_ITEM_NAME_REMOVE
1048          * WELLKNOWN, UNIQUE, UNIQUE   â†’ KDBUS_ITEM_NAME_CHANGE
1049          * UNIQUE, "", UNIQUE          â†’ KDBUS_ITEM_ID_ADD
1050          * UNIQUE, UNIQUE, ""          â†’ KDBUS_ITEM_ID_REMOVE
1051          *
1052          * For the latter two the two unique names must be identical.
1053          *
1054          * */
1055
1056         if (name) {
1057                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1058                 if (is_name_id < 0)
1059                         return 0;
1060         }
1061
1062         if (!isempty(old_owner)) {
1063                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1064                 if (r < 0)
1065                         return 0;
1066                 if (r == 0)
1067                         return 0;
1068                 if (is_name_id > 0 && old_owner_id != name_id)
1069                         return 0;
1070         } else
1071                 old_owner_id = KDBUS_MATCH_ID_ANY;
1072
1073         if (!isempty(new_owner)) {
1074                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1075                 if (r < 0)
1076                         return r;
1077                 if (r == 0)
1078                         return 0;
1079                 if (is_name_id > 0 && new_owner_id != name_id)
1080                         return 0;
1081         } else
1082                 new_owner_id = KDBUS_MATCH_ID_ANY;
1083
1084         if (is_name_id <= 0) {
1085                 struct kdbus_cmd_match *m;
1086                 size_t sz, l;
1087
1088                 /* If the name argument is missing or is a well-known
1089                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1090                  * matches for it */
1091
1092                 l = name ? strlen(name) + 1 : 0;
1093
1094                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1095                             offsetof(struct kdbus_item, name_change) +
1096                             offsetof(struct kdbus_notify_name_change, name) +
1097                             l);
1098
1099                 m = alloca0_align(sz, 8);
1100                 m->size = sz;
1101                 m->cookie = cookie;
1102
1103                 item = m->items;
1104                 item->size =
1105                         offsetof(struct kdbus_item, name_change) +
1106                         offsetof(struct kdbus_notify_name_change, name) +
1107                         l;
1108
1109                 item->name_change.old_id.id = old_owner_id;
1110                 item->name_change.new_id.id = new_owner_id;
1111
1112                 if (name)
1113                         memcpy(item->name_change.name, name, l);
1114
1115                 /* If the old name is unset or empty, then
1116                  * this can match against added names */
1117                 if (!old_owner || old_owner[0] == 0) {
1118                         item->type = KDBUS_ITEM_NAME_ADD;
1119
1120                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1121                         if (r < 0)
1122                                 return -errno;
1123                 }
1124
1125                 /* If the new name is unset or empty, then
1126                  * this can match against removed names */
1127                 if (!new_owner || new_owner[0] == 0) {
1128                         item->type = KDBUS_ITEM_NAME_REMOVE;
1129
1130                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1131                         if (r < 0)
1132                                 return -errno;
1133                 }
1134
1135                 /* The CHANGE match we need in either case, because
1136                  * what is reported as a name change by the kernel
1137                  * might just be an owner change between starter and
1138                  * normal clients. For userspace such a change should
1139                  * be considered a removal/addition, hence let's
1140                  * subscribe to this unconditionally. */
1141                 item->type = KDBUS_ITEM_NAME_CHANGE;
1142                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1143                 if (r < 0)
1144                         return -errno;
1145         }
1146
1147         if (is_name_id != 0) {
1148                 struct kdbus_cmd_match *m;
1149                 uint64_t sz;
1150
1151                 /* If the name argument is missing or is a unique
1152                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1153                  * for it */
1154
1155                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1156                             offsetof(struct kdbus_item, id_change) +
1157                             sizeof(struct kdbus_notify_id_change));
1158
1159                 m = alloca0_align(sz, 8);
1160                 m->size = sz;
1161                 m->cookie = cookie;
1162
1163                 item = m->items;
1164                 item->size =
1165                         offsetof(struct kdbus_item, id_change) +
1166                         sizeof(struct kdbus_notify_id_change);
1167                 item->id_change.id = name_id;
1168
1169                 /* If the old name is unset or empty, then this can
1170                  * match against added ids */
1171                 if (!old_owner || old_owner[0] == 0) {
1172                         item->type = KDBUS_ITEM_ID_ADD;
1173
1174                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1175                         if (r < 0)
1176                                 return -errno;
1177                 }
1178
1179                 /* If thew new name is unset or empty, then this can
1180                  * match against removed ids */
1181                 if (!new_owner || new_owner[0] == 0) {
1182                         item->type = KDBUS_ITEM_ID_REMOVE;
1183
1184                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1185                         if (r < 0)
1186                                 return -errno;
1187                 }
1188         }
1189
1190         return 0;
1191 }
1192
1193 int bus_add_match_internal_kernel(
1194                 sd_bus *bus,
1195                 struct bus_match_component *components,
1196                 unsigned n_components,
1197                 uint64_t cookie) {
1198
1199         struct kdbus_cmd_match *m;
1200         struct kdbus_item *item;
1201         uint64_t *bloom;
1202         size_t sz;
1203         const char *sender = NULL;
1204         size_t sender_length = 0;
1205         uint64_t src_id = KDBUS_MATCH_ID_ANY;
1206         bool using_bloom = false;
1207         unsigned i;
1208         bool matches_name_change = true;
1209         const char *name_change_arg[3] = {};
1210         int r;
1211
1212         assert(bus);
1213
1214         /* Monitor streams don't support matches, make this a NOP */
1215         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1216                 return 0;
1217
1218         bloom = alloca0(bus->bloom_size);
1219
1220         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1221
1222         for (i = 0; i < n_components; i++) {
1223                 struct bus_match_component *c = &components[i];
1224
1225                 switch (c->type) {
1226
1227                 case BUS_MATCH_SENDER:
1228                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1229                                 matches_name_change = false;
1230
1231                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1232                         if (r < 0)
1233                                 return r;
1234                         else if (r > 0)
1235                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1236                         else  {
1237                                 sender = c->value_str;
1238                                 sender_length = strlen(sender);
1239                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1240                         }
1241
1242                         break;
1243
1244                 case BUS_MATCH_MESSAGE_TYPE:
1245                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1246                                 matches_name_change = false;
1247
1248                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1249                         using_bloom = true;
1250                         break;
1251
1252                 case BUS_MATCH_INTERFACE:
1253                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1254                                 matches_name_change = false;
1255
1256                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1257                         using_bloom = true;
1258                         break;
1259
1260                 case BUS_MATCH_MEMBER:
1261                         if (!streq(c->value_str, "NameOwnerChanged"))
1262                                 matches_name_change = false;
1263
1264                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1265                         using_bloom = true;
1266                         break;
1267
1268                 case BUS_MATCH_PATH:
1269                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1270                                 matches_name_change = false;
1271
1272                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1273                         using_bloom = true;
1274                         break;
1275
1276                 case BUS_MATCH_PATH_NAMESPACE:
1277                         if (!streq(c->value_str, "/")) {
1278                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1279                                 using_bloom = true;
1280                         }
1281                         break;
1282
1283                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1284                         char buf[sizeof("arg")-1 + 2 + 1];
1285
1286                         if (c->type - BUS_MATCH_ARG < 3)
1287                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1288
1289                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1290                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1291                         using_bloom = true;
1292                         break;
1293                 }
1294
1295                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1296                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1297
1298                         xsprintf(buf, "arg%i-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1299                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1300                         using_bloom = true;
1301                         break;
1302                 }
1303
1304                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1305                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1306
1307                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1308                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1309                         using_bloom = true;
1310                         break;
1311                 }
1312
1313                 case BUS_MATCH_DESTINATION:
1314                         /* The bloom filter does not include
1315                            the destination, since it is only
1316                            available for broadcast messages
1317                            which do not carry a destination
1318                            since they are undirected. */
1319                         break;
1320
1321                 case BUS_MATCH_ROOT:
1322                 case BUS_MATCH_VALUE:
1323                 case BUS_MATCH_LEAF:
1324                 case _BUS_MATCH_NODE_TYPE_MAX:
1325                 case _BUS_MATCH_NODE_TYPE_INVALID:
1326                         assert_not_reached("Invalid match type?");
1327                 }
1328         }
1329
1330         if (using_bloom)
1331                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1332
1333         m = alloca0_align(sz, 8);
1334         m->size = sz;
1335         m->cookie = cookie;
1336
1337         item = m->items;
1338
1339         if (src_id != KDBUS_MATCH_ID_ANY) {
1340                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1341                 item->type = KDBUS_ITEM_ID;
1342                 item->id = src_id;
1343                 item = KDBUS_ITEM_NEXT(item);
1344         }
1345
1346         if (using_bloom) {
1347                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1348                 item->type = KDBUS_ITEM_BLOOM_MASK;
1349                 memcpy(item->data64, bloom, bus->bloom_size);
1350                 item = KDBUS_ITEM_NEXT(item);
1351         }
1352
1353         if (sender) {
1354                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1355                 item->type = KDBUS_ITEM_NAME;
1356                 memcpy(item->str, sender, sender_length + 1);
1357         }
1358
1359         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1360         if (r < 0)
1361                 return -errno;
1362
1363         if (matches_name_change) {
1364
1365                 /* If this match could theoretically match
1366                  * NameOwnerChanged messages, we need to
1367                  * install a second non-bloom filter explitly
1368                  * for it */
1369
1370                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1371                 if (r < 0)
1372                         return r;
1373         }
1374
1375         return 0;
1376 }
1377
1378 #define internal_match(bus, m)                                          \
1379         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1380          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1381          : (m))
1382
1383 static int bus_add_match_internal_dbus1(
1384                 sd_bus *bus,
1385                 const char *match) {
1386
1387         const char *e;
1388
1389         assert(bus);
1390         assert(match);
1391
1392         e = internal_match(bus, match);
1393
1394         return sd_bus_call_method(
1395                         bus,
1396                         "org.freedesktop.DBus",
1397                         "/org/freedesktop/DBus",
1398                         "org.freedesktop.DBus",
1399                         "AddMatch",
1400                         NULL,
1401                         NULL,
1402                         "s",
1403                         e);
1404 }
1405
1406 int bus_add_match_internal(
1407                 sd_bus *bus,
1408                 const char *match,
1409                 struct bus_match_component *components,
1410                 unsigned n_components,
1411                 uint64_t cookie) {
1412
1413         assert(bus);
1414
1415         if (!bus->bus_client)
1416                 return -EINVAL;
1417
1418         if (bus->is_kernel)
1419                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1420         else
1421                 return bus_add_match_internal_dbus1(bus, match);
1422 }
1423
1424 int bus_remove_match_internal_kernel(
1425                 sd_bus *bus,
1426                 uint64_t cookie) {
1427
1428         struct kdbus_cmd_match m = {
1429                 .size = offsetof(struct kdbus_cmd_match, items),
1430                 .cookie = cookie,
1431         };
1432         int r;
1433
1434         assert(bus);
1435
1436         /* Monitor streams don't support matches, make this a NOP */
1437         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1438                 return 0;
1439
1440         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1441         if (r < 0)
1442                 return -errno;
1443
1444         return 0;
1445 }
1446
1447 static int bus_remove_match_internal_dbus1(
1448                 sd_bus *bus,
1449                 const char *match) {
1450
1451         const char *e;
1452
1453         assert(bus);
1454         assert(match);
1455
1456         e = internal_match(bus, match);
1457
1458         return sd_bus_call_method(
1459                         bus,
1460                         "org.freedesktop.DBus",
1461                         "/org/freedesktop/DBus",
1462                         "org.freedesktop.DBus",
1463                         "RemoveMatch",
1464                         NULL,
1465                         NULL,
1466                         "s",
1467                         e);
1468 }
1469
1470 int bus_remove_match_internal(
1471                 sd_bus *bus,
1472                 const char *match,
1473                 uint64_t cookie) {
1474
1475         assert(bus);
1476
1477         if (!bus->bus_client)
1478                 return -EINVAL;
1479
1480         if (bus->is_kernel)
1481                 return bus_remove_match_internal_kernel(bus, cookie);
1482         else
1483                 return bus_remove_match_internal_dbus1(bus, match);
1484 }
1485
1486 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1487         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1488         const char *mid;
1489         int r;
1490
1491         assert_return(bus, -EINVAL);
1492         assert_return(name, -EINVAL);
1493         assert_return(machine, -EINVAL);
1494         assert_return(!bus_pid_changed(bus), -ECHILD);
1495         assert_return(service_name_is_valid(name), -EINVAL);
1496
1497         if (!bus->bus_client)
1498                 return -EINVAL;
1499
1500         if (!BUS_IS_OPEN(bus->state))
1501                 return -ENOTCONN;
1502
1503         if (streq_ptr(name, bus->unique_name))
1504                 return sd_id128_get_machine(machine);
1505
1506         r = sd_bus_message_new_method_call(
1507                         bus,
1508                         &m,
1509                         name,
1510                         "/",
1511                         "org.freedesktop.DBus.Peer",
1512                         "GetMachineId");
1513         if (r < 0)
1514                 return r;
1515
1516         r = sd_bus_message_set_auto_start(m, false);
1517         if (r < 0)
1518                 return r;
1519
1520         r = sd_bus_call(bus, m, 0, NULL, &reply);
1521         if (r < 0)
1522                 return r;
1523
1524         r = sd_bus_message_read(reply, "s", &mid);
1525         if (r < 0)
1526                 return r;
1527
1528         return sd_id128_from_string(mid, machine);
1529 }