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