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