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