chiark / gitweb /
b31549b03e9e8b6107a53bf0e53b29ad7b2b43c8
[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", 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_SUPPLEMENTARY_GIDS|
682                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
683                      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|
684                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
685                      SD_BUS_CREDS_SELINUX_CONTEXT|
686                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
687                 mask |= SD_BUS_CREDS_PID;
688
689         cmd->size = size;
690         cmd->attach_flags = attach_flags_to_kdbus(mask);
691
692         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
693         if (r < 0)
694                 return -errno;
695
696         conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
697
698         /* Non-activated names are considered not available */
699         if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
700                 if (name[0] == ':')
701                         r = -ENXIO;
702                 else
703                         r = -ESRCH;
704                 goto fail;
705         }
706
707         c = bus_creds_new();
708         if (!c) {
709                 r = -ENOMEM;
710                 goto fail;
711         }
712
713         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
714                 if (asprintf(&c->unique_name, ":1.%llu", conn_info->id) < 0) {
715                         r = -ENOMEM;
716                         goto fail;
717                 }
718
719                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
720         }
721
722         /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
723            them in case the service has no names. This does not mean
724            however that the list of owned names could not be
725            acquired. Hence, let's explicitly clarify that the data is
726            complete. */
727         c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
728
729         r = bus_populate_creds_from_items(bus, conn_info, mask, c);
730         if (r < 0)
731                 goto fail;
732
733         r = bus_creds_add_more(c, mask, 0, 0);
734         if (r < 0)
735                 goto fail;
736
737         if (creds) {
738                 *creds = c;
739                 c = NULL;
740         }
741
742         r = 0;
743
744 fail:
745         bus_kernel_cmd_free(bus, cmd->offset);
746         return r;
747 }
748
749 static int bus_get_name_creds_dbus1(
750                 sd_bus *bus,
751                 const char *name,
752                 uint64_t mask,
753                 sd_bus_creds **creds) {
754
755         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
756         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
757         const char *unique = NULL;
758         pid_t pid = 0;
759         int r;
760
761         /* Only query the owner if the caller wants to know it or if
762          * the caller just wants to check whether a name exists */
763         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
764                 r = sd_bus_call_method(
765                                 bus,
766                                 "org.freedesktop.DBus",
767                                 "/org/freedesktop/DBus",
768                                 "org.freedesktop.DBus",
769                                 "GetNameOwner",
770                                 NULL,
771                                 &reply_unique,
772                                 "s",
773                                 name);
774                 if (r < 0)
775                         return r;
776
777                 r = sd_bus_message_read(reply_unique, "s", &unique);
778                 if (r < 0)
779                         return r;
780         }
781
782         if (mask != 0) {
783                 c = bus_creds_new();
784                 if (!c)
785                         return -ENOMEM;
786
787                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
788                         c->unique_name = strdup(unique);
789                         if (!c->unique_name)
790                                 return -ENOMEM;
791
792                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
793                 }
794
795                 if ((mask & SD_BUS_CREDS_PID) ||
796                     ((mask & SD_BUS_CREDS_AUGMENT) &&
797                      (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
798                               SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
799                               SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
800                               SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
801                               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|
802                               SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
803                               SD_BUS_CREDS_SELINUX_CONTEXT|
804                               SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
805
806                         uint32_t u;
807
808                         r = sd_bus_call_method(
809                                         bus,
810                                         "org.freedesktop.DBus",
811                                         "/org/freedesktop/DBus",
812                                         "org.freedesktop.DBus",
813                                         "GetConnectionUnixProcessID",
814                                         NULL,
815                                         &reply,
816                                         "s",
817                                         unique ? unique : name);
818                         if (r < 0)
819                                 return r;
820
821                         r = sd_bus_message_read(reply, "u", &u);
822                         if (r < 0)
823                                 return r;
824
825                         pid = u;
826                         if (mask & SD_BUS_CREDS_PID) {
827                                 c->pid = u;
828                                 c->mask |= SD_BUS_CREDS_PID;
829                         }
830
831                         reply = sd_bus_message_unref(reply);
832                 }
833
834                 if (mask & SD_BUS_CREDS_EUID) {
835                         uint32_t u;
836
837                         r = sd_bus_call_method(
838                                         bus,
839                                         "org.freedesktop.DBus",
840                                         "/org/freedesktop/DBus",
841                                         "org.freedesktop.DBus",
842                                         "GetConnectionUnixUser",
843                                         NULL,
844                                         &reply,
845                                         "s",
846                                         unique ? unique : name);
847                         if (r < 0)
848                                 return r;
849
850                         r = sd_bus_message_read(reply, "u", &u);
851                         if (r < 0)
852                                 return r;
853
854                         c->euid = u;
855                         c->mask |= SD_BUS_CREDS_EUID;
856
857                         reply = sd_bus_message_unref(reply);
858                 }
859
860                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
861                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
862                         const void *p = NULL;
863                         size_t sz = 0;
864
865                         r = sd_bus_call_method(
866                                         bus,
867                                         "org.freedesktop.DBus",
868                                         "/org/freedesktop/DBus",
869                                         "org.freedesktop.DBus",
870                                         "GetConnectionSELinuxSecurityContext",
871                                         &error,
872                                         &reply,
873                                         "s",
874                                         unique ? unique : name);
875                         if (r < 0) {
876                                 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
877                                         return r;
878                         } else {
879                                 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
880                                 if (r < 0)
881                                         return r;
882
883                                 c->label = strndup(p, sz);
884                                 if (!c->label)
885                                         return -ENOMEM;
886
887                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
888                         }
889                 }
890
891                 r = bus_creds_add_more(c, mask, pid, 0);
892                 if (r < 0)
893                         return r;
894         }
895
896         if (creds) {
897                 *creds = c;
898                 c = NULL;
899         }
900
901         return 0;
902 }
903
904 _public_ int sd_bus_get_name_creds(
905                 sd_bus *bus,
906                 const char *name,
907                 uint64_t mask,
908                 sd_bus_creds **creds) {
909
910         assert_return(bus, -EINVAL);
911         assert_return(name, -EINVAL);
912         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
913         assert_return(mask == 0 || creds, -EINVAL);
914         assert_return(!bus_pid_changed(bus), -ECHILD);
915         assert_return(service_name_is_valid(name), -EINVAL);
916
917         if (!bus->bus_client)
918                 return -EINVAL;
919
920         if (streq(name, "org.freedesktop.DBus.Local"))
921                 return -EINVAL;
922
923         if (!BUS_IS_OPEN(bus->state))
924                 return -ENOTCONN;
925
926         if (bus->is_kernel)
927                 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
928         else
929                 return bus_get_name_creds_dbus1(bus, name, mask, creds);
930 }
931
932 static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
933         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
934         struct kdbus_cmd_info cmd = {
935                 .size = sizeof(struct kdbus_cmd_info),
936         };
937         struct kdbus_info *creator_info;
938         pid_t pid = 0;
939         int r;
940
941         c = bus_creds_new();
942         if (!c)
943                 return -ENOMEM;
944
945         /* If augmentation is on, and the bus doesn't didn't allow us
946          * to get the bits we want, then ask for the PID/TID so that we
947          * can read the rest from /proc. */
948         if ((mask & SD_BUS_CREDS_AUGMENT) &&
949             (mask & (SD_BUS_CREDS_PPID|
950                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
951                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
952                      SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
953                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
954                      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|
955                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
956                      SD_BUS_CREDS_SELINUX_CONTEXT|
957                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
958                 mask |= SD_BUS_CREDS_PID;
959
960         cmd.attach_flags = attach_flags_to_kdbus(mask);
961
962         r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
963         if (r < 0)
964                 return -errno;
965
966         creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
967
968         r = bus_populate_creds_from_items(bus, creator_info, mask, c);
969         bus_kernel_cmd_free(bus, cmd.offset);
970         if (r < 0)
971                 return r;
972
973         r = bus_creds_add_more(c, mask, pid, 0);
974         if (r < 0)
975                 return r;
976
977         *ret = c;
978         c = NULL;
979         return 0;
980 }
981
982 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
983         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
984         pid_t pid = 0;
985         bool do_label;
986         int r;
987
988         assert(bus);
989
990         do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
991
992         /* Avoid allocating anything if we have no chance of returning useful data */
993         if (!bus->ucred_valid && !do_label)
994                 return -ENODATA;
995
996         c = bus_creds_new();
997         if (!c)
998                 return -ENOMEM;
999
1000         if (bus->ucred_valid) {
1001                 if (bus->ucred.pid > 0) {
1002                         pid = c->pid = bus->ucred.pid;
1003                         c->mask |= SD_BUS_CREDS_PID & mask;
1004                 }
1005
1006                 if (bus->ucred.uid != UID_INVALID) {
1007                         c->euid = bus->ucred.uid;
1008                         c->mask |= SD_BUS_CREDS_EUID & mask;
1009                 }
1010
1011                 if (bus->ucred.gid != GID_INVALID) {
1012                         c->egid = bus->ucred.gid;
1013                         c->mask |= SD_BUS_CREDS_EGID & mask;
1014                 }
1015         }
1016
1017         if (do_label) {
1018                 c->label = strdup(bus->label);
1019                 if (!c->label)
1020                         return -ENOMEM;
1021
1022                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1023         }
1024
1025         r = bus_creds_add_more(c, mask, pid, 0);
1026         if (r < 0)
1027                 return r;
1028
1029         *ret = c;
1030         c = NULL;
1031         return 0;
1032 }
1033
1034 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
1035         assert_return(bus, -EINVAL);
1036         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
1037         assert_return(ret, -EINVAL);
1038         assert_return(!bus_pid_changed(bus), -ECHILD);
1039
1040         if (!BUS_IS_OPEN(bus->state))
1041                 return -ENOTCONN;
1042
1043         if (bus->is_kernel)
1044                 return bus_get_owner_creds_kdbus(bus, mask, ret);
1045         else
1046                 return bus_get_owner_creds_dbus1(bus, mask, ret);
1047 }
1048
1049 static int add_name_change_match(sd_bus *bus,
1050                                  uint64_t cookie,
1051                                  const char *name,
1052                                  const char *old_owner,
1053                                  const char *new_owner) {
1054
1055         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
1056         int is_name_id = -1, r;
1057         struct kdbus_item *item;
1058
1059         assert(bus);
1060
1061         /* If we encounter a match that could match against
1062          * NameOwnerChanged messages, then we need to create
1063          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1064          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1065          * multiple if the match is underspecified.
1066          *
1067          * The NameOwnerChanged signals take three parameters with
1068          * unique or well-known names, but only some forms actually
1069          * exist:
1070          *
1071          * WELLKNOWN, "", UNIQUE       → KDBUS_ITEM_NAME_ADD
1072          * WELLKNOWN, UNIQUE, ""       → KDBUS_ITEM_NAME_REMOVE
1073          * WELLKNOWN, UNIQUE, UNIQUE   → KDBUS_ITEM_NAME_CHANGE
1074          * UNIQUE, "", UNIQUE          → KDBUS_ITEM_ID_ADD
1075          * UNIQUE, UNIQUE, ""          → KDBUS_ITEM_ID_REMOVE
1076          *
1077          * For the latter two the two unique names must be identical.
1078          *
1079          * */
1080
1081         if (name) {
1082                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1083                 if (is_name_id < 0)
1084                         return 0;
1085         }
1086
1087         if (!isempty(old_owner)) {
1088                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1089                 if (r < 0)
1090                         return 0;
1091                 if (r == 0)
1092                         return 0;
1093                 if (is_name_id > 0 && old_owner_id != name_id)
1094                         return 0;
1095         } else
1096                 old_owner_id = KDBUS_MATCH_ID_ANY;
1097
1098         if (!isempty(new_owner)) {
1099                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1100                 if (r < 0)
1101                         return r;
1102                 if (r == 0)
1103                         return 0;
1104                 if (is_name_id > 0 && new_owner_id != name_id)
1105                         return 0;
1106         } else
1107                 new_owner_id = KDBUS_MATCH_ID_ANY;
1108
1109         if (is_name_id <= 0) {
1110                 struct kdbus_cmd_match *m;
1111                 size_t sz, l;
1112
1113                 /* If the name argument is missing or is a well-known
1114                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1115                  * matches for it */
1116
1117                 l = name ? strlen(name) + 1 : 0;
1118
1119                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1120                             offsetof(struct kdbus_item, name_change) +
1121                             offsetof(struct kdbus_notify_name_change, name) +
1122                             l);
1123
1124                 m = alloca0_align(sz, 8);
1125                 m->size = sz;
1126                 m->cookie = cookie;
1127
1128                 item = m->items;
1129                 item->size =
1130                         offsetof(struct kdbus_item, name_change) +
1131                         offsetof(struct kdbus_notify_name_change, name) +
1132                         l;
1133
1134                 item->name_change.old_id.id = old_owner_id;
1135                 item->name_change.new_id.id = new_owner_id;
1136
1137                 memcpy_safe(item->name_change.name, name, l);
1138
1139                 /* If the old name is unset or empty, then
1140                  * this can match against added names */
1141                 if (isempty(old_owner)) {
1142                         item->type = KDBUS_ITEM_NAME_ADD;
1143
1144                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1145                         if (r < 0)
1146                                 return -errno;
1147                 }
1148
1149                 /* If the new name is unset or empty, then
1150                  * this can match against removed names */
1151                 if (isempty(new_owner)) {
1152                         item->type = KDBUS_ITEM_NAME_REMOVE;
1153
1154                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1155                         if (r < 0)
1156                                 return -errno;
1157                 }
1158
1159                 /* The CHANGE match we need in either case, because
1160                  * what is reported as a name change by the kernel
1161                  * might just be an owner change between starter and
1162                  * normal clients. For userspace such a change should
1163                  * be considered a removal/addition, hence let's
1164                  * subscribe to this unconditionally. */
1165                 item->type = KDBUS_ITEM_NAME_CHANGE;
1166                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1167                 if (r < 0)
1168                         return -errno;
1169         }
1170
1171         if (is_name_id != 0) {
1172                 struct kdbus_cmd_match *m;
1173                 uint64_t sz;
1174
1175                 /* If the name argument is missing or is a unique
1176                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1177                  * for it */
1178
1179                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1180                             offsetof(struct kdbus_item, id_change) +
1181                             sizeof(struct kdbus_notify_id_change));
1182
1183                 m = alloca0_align(sz, 8);
1184                 m->size = sz;
1185                 m->cookie = cookie;
1186
1187                 item = m->items;
1188                 item->size =
1189                         offsetof(struct kdbus_item, id_change) +
1190                         sizeof(struct kdbus_notify_id_change);
1191                 item->id_change.id = name_id;
1192
1193                 /* If the old name is unset or empty, then this can
1194                  * match against added ids */
1195                 if (isempty(old_owner)) {
1196                         item->type = KDBUS_ITEM_ID_ADD;
1197                         if (!isempty(new_owner))
1198                                 item->id_change.id = new_owner_id;
1199
1200                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1201                         if (r < 0)
1202                                 return -errno;
1203                 }
1204
1205                 /* If thew new name is unset or empty, then this can
1206                  * match against removed ids */
1207                 if (isempty(new_owner)) {
1208                         item->type = KDBUS_ITEM_ID_REMOVE;
1209                         if (!isempty(old_owner))
1210                                 item->id_change.id = old_owner_id;
1211
1212                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1213                         if (r < 0)
1214                                 return -errno;
1215                 }
1216         }
1217
1218         return 0;
1219 }
1220
1221 int bus_add_match_internal_kernel(
1222                 sd_bus *bus,
1223                 struct bus_match_component *components,
1224                 unsigned n_components,
1225                 uint64_t cookie) {
1226
1227         struct kdbus_cmd_match *m;
1228         struct kdbus_item *item;
1229         uint64_t *bloom;
1230         size_t sz;
1231         const char *sender = NULL;
1232         size_t sender_length = 0;
1233         uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
1234         bool using_bloom = false;
1235         unsigned i;
1236         bool matches_name_change = true;
1237         const char *name_change_arg[3] = {};
1238         int r;
1239
1240         assert(bus);
1241
1242         /* Monitor streams don't support matches, make this a NOP */
1243         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1244                 return 0;
1245
1246         bloom = alloca0(bus->bloom_size);
1247
1248         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1249
1250         for (i = 0; i < n_components; i++) {
1251                 struct bus_match_component *c = &components[i];
1252
1253                 switch (c->type) {
1254
1255                 case BUS_MATCH_SENDER:
1256                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1257                                 matches_name_change = false;
1258
1259                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1260                         if (r < 0)
1261                                 return r;
1262                         else if (r > 0)
1263                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1264                         else  {
1265                                 sender = c->value_str;
1266                                 sender_length = strlen(sender);
1267                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1268                         }
1269
1270                         break;
1271
1272                 case BUS_MATCH_MESSAGE_TYPE:
1273                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1274                                 matches_name_change = false;
1275
1276                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1277                         using_bloom = true;
1278                         break;
1279
1280                 case BUS_MATCH_INTERFACE:
1281                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1282                                 matches_name_change = false;
1283
1284                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1285                         using_bloom = true;
1286                         break;
1287
1288                 case BUS_MATCH_MEMBER:
1289                         if (!streq(c->value_str, "NameOwnerChanged"))
1290                                 matches_name_change = false;
1291
1292                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1293                         using_bloom = true;
1294                         break;
1295
1296                 case BUS_MATCH_PATH:
1297                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1298                                 matches_name_change = false;
1299
1300                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1301                         using_bloom = true;
1302                         break;
1303
1304                 case BUS_MATCH_PATH_NAMESPACE:
1305                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1306                         using_bloom = true;
1307                         break;
1308
1309                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1310                         char buf[sizeof("arg")-1 + 2 + 1];
1311
1312                         if (c->type - BUS_MATCH_ARG < 3)
1313                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1314
1315                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1316                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1317                         using_bloom = true;
1318                         break;
1319                 }
1320
1321                 case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
1322                         char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
1323
1324                         xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
1325                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1326                         using_bloom = true;
1327                         break;
1328                 }
1329
1330                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
1331                         /*
1332                          * XXX: DBus spec defines arg[0..63]path= matching to be
1333                          * a two-way glob. That is, if either string is a prefix
1334                          * of the other, it matches.
1335                          * This is really hard to realize in bloom-filters, as
1336                          * we would have to create a bloom-match for each prefix
1337                          * of @c->value_str. This is excessive, hence we just
1338                          * ignore all those matches and accept everything from
1339                          * the kernel. People should really avoid those matches.
1340                          * If they're used in real-life some day, we will have
1341                          * to properly support multiple-matches here.
1342                          */
1343                         break;
1344
1345                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1346                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1347
1348                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1349                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1350                         using_bloom = true;
1351                         break;
1352                 }
1353
1354                 case BUS_MATCH_DESTINATION:
1355                         /*
1356                          * Kernel only supports matching on destination IDs, but
1357                          * not on destination names. So just skip the
1358                          * destination name restriction and verify it in
1359                          * user-space on retrieval.
1360                          */
1361                         r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
1362                         if (r < 0)
1363                                 return r;
1364                         else if (r > 0)
1365                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1366
1367                         /* if not a broadcast, it cannot be a name-change */
1368                         if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
1369                                 matches_name_change = false;
1370
1371                         break;
1372
1373                 case BUS_MATCH_ROOT:
1374                 case BUS_MATCH_VALUE:
1375                 case BUS_MATCH_LEAF:
1376                 case _BUS_MATCH_NODE_TYPE_MAX:
1377                 case _BUS_MATCH_NODE_TYPE_INVALID:
1378                         assert_not_reached("Invalid match type?");
1379                 }
1380         }
1381
1382         if (using_bloom)
1383                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1384
1385         m = alloca0_align(sz, 8);
1386         m->size = sz;
1387         m->cookie = cookie;
1388
1389         item = m->items;
1390
1391         if (src_id != KDBUS_MATCH_ID_ANY) {
1392                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1393                 item->type = KDBUS_ITEM_ID;
1394                 item->id = src_id;
1395                 item = KDBUS_ITEM_NEXT(item);
1396         }
1397
1398         if (dst_id != KDBUS_MATCH_ID_ANY) {
1399                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1400                 item->type = KDBUS_ITEM_DST_ID;
1401                 item->id = dst_id;
1402                 item = KDBUS_ITEM_NEXT(item);
1403         }
1404
1405         if (using_bloom) {
1406                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1407                 item->type = KDBUS_ITEM_BLOOM_MASK;
1408                 memcpy(item->data64, bloom, bus->bloom_size);
1409                 item = KDBUS_ITEM_NEXT(item);
1410         }
1411
1412         if (sender) {
1413                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1414                 item->type = KDBUS_ITEM_NAME;
1415                 memcpy(item->str, sender, sender_length + 1);
1416         }
1417
1418         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1419         if (r < 0)
1420                 return -errno;
1421
1422         if (matches_name_change) {
1423
1424                 /* If this match could theoretically match
1425                  * NameOwnerChanged messages, we need to
1426                  * install a second non-bloom filter explitly
1427                  * for it */
1428
1429                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1430                 if (r < 0)
1431                         return r;
1432         }
1433
1434         return 0;
1435 }
1436
1437 #define internal_match(bus, m)                                          \
1438         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1439          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1440          : (m))
1441
1442 static int bus_add_match_internal_dbus1(
1443                 sd_bus *bus,
1444                 const char *match) {
1445
1446         const char *e;
1447
1448         assert(bus);
1449         assert(match);
1450
1451         e = internal_match(bus, match);
1452
1453         return sd_bus_call_method(
1454                         bus,
1455                         "org.freedesktop.DBus",
1456                         "/org/freedesktop/DBus",
1457                         "org.freedesktop.DBus",
1458                         "AddMatch",
1459                         NULL,
1460                         NULL,
1461                         "s",
1462                         e);
1463 }
1464
1465 int bus_add_match_internal(
1466                 sd_bus *bus,
1467                 const char *match,
1468                 struct bus_match_component *components,
1469                 unsigned n_components,
1470                 uint64_t cookie) {
1471
1472         assert(bus);
1473
1474         if (!bus->bus_client)
1475                 return -EINVAL;
1476
1477         if (bus->is_kernel)
1478                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1479         else
1480                 return bus_add_match_internal_dbus1(bus, match);
1481 }
1482
1483 int bus_remove_match_internal_kernel(
1484                 sd_bus *bus,
1485                 uint64_t cookie) {
1486
1487         struct kdbus_cmd_match m = {
1488                 .size = offsetof(struct kdbus_cmd_match, items),
1489                 .cookie = cookie,
1490         };
1491         int r;
1492
1493         assert(bus);
1494
1495         /* Monitor streams don't support matches, make this a NOP */
1496         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1497                 return 0;
1498
1499         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1500         if (r < 0)
1501                 return -errno;
1502
1503         return 0;
1504 }
1505
1506 static int bus_remove_match_internal_dbus1(
1507                 sd_bus *bus,
1508                 const char *match) {
1509
1510         const char *e;
1511
1512         assert(bus);
1513         assert(match);
1514
1515         e = internal_match(bus, match);
1516
1517         return sd_bus_call_method(
1518                         bus,
1519                         "org.freedesktop.DBus",
1520                         "/org/freedesktop/DBus",
1521                         "org.freedesktop.DBus",
1522                         "RemoveMatch",
1523                         NULL,
1524                         NULL,
1525                         "s",
1526                         e);
1527 }
1528
1529 int bus_remove_match_internal(
1530                 sd_bus *bus,
1531                 const char *match,
1532                 uint64_t cookie) {
1533
1534         assert(bus);
1535
1536         if (!bus->bus_client)
1537                 return -EINVAL;
1538
1539         if (bus->is_kernel)
1540                 return bus_remove_match_internal_kernel(bus, cookie);
1541         else
1542                 return bus_remove_match_internal_dbus1(bus, match);
1543 }
1544
1545 #if 0 /// UNNEEDED by elogind
1546 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1547         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
1548         const char *mid;
1549         int r;
1550
1551         assert_return(bus, -EINVAL);
1552         assert_return(name, -EINVAL);
1553         assert_return(machine, -EINVAL);
1554         assert_return(!bus_pid_changed(bus), -ECHILD);
1555         assert_return(service_name_is_valid(name), -EINVAL);
1556
1557         if (!bus->bus_client)
1558                 return -EINVAL;
1559
1560         if (!BUS_IS_OPEN(bus->state))
1561                 return -ENOTCONN;
1562
1563         if (streq_ptr(name, bus->unique_name))
1564                 return sd_id128_get_machine(machine);
1565
1566         r = sd_bus_message_new_method_call(
1567                         bus,
1568                         &m,
1569                         name,
1570                         "/",
1571                         "org.freedesktop.DBus.Peer",
1572                         "GetMachineId");
1573         if (r < 0)
1574                 return r;
1575
1576         r = sd_bus_message_set_auto_start(m, false);
1577         if (r < 0)
1578                 return r;
1579
1580         r = sd_bus_call(bus, m, 0, NULL, &reply);
1581         if (r < 0)
1582                 return r;
1583
1584         r = sd_bus_message_read(reply, "s", &mid);
1585         if (r < 0)
1586                 return r;
1587
1588         return sd_id128_from_string(mid, machine);
1589 }
1590 #endif // 0