chiark / gitweb /
Prep v229: Add missing fixes from upstream [3/6] src/libelogind
[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                 if (name)
1135                         memcpy(item->name_change.name, name, l);
1136
1137                 /* If the old name is unset or empty, then
1138                  * this can match against added names */
1139                 if (isempty(old_owner)) {
1140                         item->type = KDBUS_ITEM_NAME_ADD;
1141
1142                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1143                         if (r < 0)
1144                                 return -errno;
1145                 }
1146
1147                 /* If the new name is unset or empty, then
1148                  * this can match against removed names */
1149                 if (isempty(new_owner)) {
1150                         item->type = KDBUS_ITEM_NAME_REMOVE;
1151
1152                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1153                         if (r < 0)
1154                                 return -errno;
1155                 }
1156
1157                 /* The CHANGE match we need in either case, because
1158                  * what is reported as a name change by the kernel
1159                  * might just be an owner change between starter and
1160                  * normal clients. For userspace such a change should
1161                  * be considered a removal/addition, hence let's
1162                  * subscribe to this unconditionally. */
1163                 item->type = KDBUS_ITEM_NAME_CHANGE;
1164                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1165                 if (r < 0)
1166                         return -errno;
1167         }
1168
1169         if (is_name_id != 0) {
1170                 struct kdbus_cmd_match *m;
1171                 uint64_t sz;
1172
1173                 /* If the name argument is missing or is a unique
1174                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1175                  * for it */
1176
1177                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1178                             offsetof(struct kdbus_item, id_change) +
1179                             sizeof(struct kdbus_notify_id_change));
1180
1181                 m = alloca0_align(sz, 8);
1182                 m->size = sz;
1183                 m->cookie = cookie;
1184
1185                 item = m->items;
1186                 item->size =
1187                         offsetof(struct kdbus_item, id_change) +
1188                         sizeof(struct kdbus_notify_id_change);
1189                 item->id_change.id = name_id;
1190
1191                 /* If the old name is unset or empty, then this can
1192                  * match against added ids */
1193                 if (isempty(old_owner)) {
1194                         item->type = KDBUS_ITEM_ID_ADD;
1195                         if (!isempty(new_owner))
1196                                 item->id_change.id = new_owner_id;
1197
1198                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1199                         if (r < 0)
1200                                 return -errno;
1201                 }
1202
1203                 /* If thew new name is unset or empty, then this can
1204                  * match against removed ids */
1205                 if (isempty(new_owner)) {
1206                         item->type = KDBUS_ITEM_ID_REMOVE;
1207                         if (!isempty(old_owner))
1208                                 item->id_change.id = old_owner_id;
1209
1210                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1211                         if (r < 0)
1212                                 return -errno;
1213                 }
1214         }
1215
1216         return 0;
1217 }
1218
1219 int bus_add_match_internal_kernel(
1220                 sd_bus *bus,
1221                 struct bus_match_component *components,
1222                 unsigned n_components,
1223                 uint64_t cookie) {
1224
1225         struct kdbus_cmd_match *m;
1226         struct kdbus_item *item;
1227         uint64_t *bloom;
1228         size_t sz;
1229         const char *sender = NULL;
1230         size_t sender_length = 0;
1231         uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
1232         bool using_bloom = false;
1233         unsigned i;
1234         bool matches_name_change = true;
1235         const char *name_change_arg[3] = {};
1236         int r;
1237
1238         assert(bus);
1239
1240         /* Monitor streams don't support matches, make this a NOP */
1241         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1242                 return 0;
1243
1244         bloom = alloca0(bus->bloom_size);
1245
1246         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1247
1248         for (i = 0; i < n_components; i++) {
1249                 struct bus_match_component *c = &components[i];
1250
1251                 switch (c->type) {
1252
1253                 case BUS_MATCH_SENDER:
1254                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1255                                 matches_name_change = false;
1256
1257                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1258                         if (r < 0)
1259                                 return r;
1260                         else if (r > 0)
1261                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1262                         else  {
1263                                 sender = c->value_str;
1264                                 sender_length = strlen(sender);
1265                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1266                         }
1267
1268                         break;
1269
1270                 case BUS_MATCH_MESSAGE_TYPE:
1271                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1272                                 matches_name_change = false;
1273
1274                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1275                         using_bloom = true;
1276                         break;
1277
1278                 case BUS_MATCH_INTERFACE:
1279                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1280                                 matches_name_change = false;
1281
1282                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1283                         using_bloom = true;
1284                         break;
1285
1286                 case BUS_MATCH_MEMBER:
1287                         if (!streq(c->value_str, "NameOwnerChanged"))
1288                                 matches_name_change = false;
1289
1290                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1291                         using_bloom = true;
1292                         break;
1293
1294                 case BUS_MATCH_PATH:
1295                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1296                                 matches_name_change = false;
1297
1298                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1299                         using_bloom = true;
1300                         break;
1301
1302                 case BUS_MATCH_PATH_NAMESPACE:
1303                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1304                         using_bloom = true;
1305                         break;
1306
1307                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1308                         char buf[sizeof("arg")-1 + 2 + 1];
1309
1310                         if (c->type - BUS_MATCH_ARG < 3)
1311                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1312
1313                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1314                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1315                         using_bloom = true;
1316                         break;
1317                 }
1318
1319                 case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
1320                         char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
1321
1322                         xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
1323                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1324                         using_bloom = true;
1325                         break;
1326                 }
1327
1328                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
1329                         /*
1330                          * XXX: DBus spec defines arg[0..63]path= matching to be
1331                          * a two-way glob. That is, if either string is a prefix
1332                          * of the other, it matches.
1333                          * This is really hard to realize in bloom-filters, as
1334                          * we would have to create a bloom-match for each prefix
1335                          * of @c->value_str. This is excessive, hence we just
1336                          * ignore all those matches and accept everything from
1337                          * the kernel. People should really avoid those matches.
1338                          * If they're used in real-life some day, we will have
1339                          * to properly support multiple-matches here.
1340                          */
1341                         break;
1342
1343                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1344                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1345
1346                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1347                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1348                         using_bloom = true;
1349                         break;
1350                 }
1351
1352                 case BUS_MATCH_DESTINATION:
1353                         /*
1354                          * Kernel only supports matching on destination IDs, but
1355                          * not on destination names. So just skip the
1356                          * destination name restriction and verify it in
1357                          * user-space on retrieval.
1358                          */
1359                         r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
1360                         if (r < 0)
1361                                 return r;
1362                         else if (r > 0)
1363                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1364
1365                         /* if not a broadcast, it cannot be a name-change */
1366                         if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
1367                                 matches_name_change = false;
1368
1369                         break;
1370
1371                 case BUS_MATCH_ROOT:
1372                 case BUS_MATCH_VALUE:
1373                 case BUS_MATCH_LEAF:
1374                 case _BUS_MATCH_NODE_TYPE_MAX:
1375                 case _BUS_MATCH_NODE_TYPE_INVALID:
1376                         assert_not_reached("Invalid match type?");
1377                 }
1378         }
1379
1380         if (using_bloom)
1381                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1382
1383         m = alloca0_align(sz, 8);
1384         m->size = sz;
1385         m->cookie = cookie;
1386
1387         item = m->items;
1388
1389         if (src_id != KDBUS_MATCH_ID_ANY) {
1390                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1391                 item->type = KDBUS_ITEM_ID;
1392                 item->id = src_id;
1393                 item = KDBUS_ITEM_NEXT(item);
1394         }
1395
1396         if (dst_id != KDBUS_MATCH_ID_ANY) {
1397                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1398                 item->type = KDBUS_ITEM_DST_ID;
1399                 item->id = dst_id;
1400                 item = KDBUS_ITEM_NEXT(item);
1401         }
1402
1403         if (using_bloom) {
1404                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1405                 item->type = KDBUS_ITEM_BLOOM_MASK;
1406                 memcpy(item->data64, bloom, bus->bloom_size);
1407                 item = KDBUS_ITEM_NEXT(item);
1408         }
1409
1410         if (sender) {
1411                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1412                 item->type = KDBUS_ITEM_NAME;
1413                 memcpy(item->str, sender, sender_length + 1);
1414         }
1415
1416         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1417         if (r < 0)
1418                 return -errno;
1419
1420         if (matches_name_change) {
1421
1422                 /* If this match could theoretically match
1423                  * NameOwnerChanged messages, we need to
1424                  * install a second non-bloom filter explitly
1425                  * for it */
1426
1427                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1428                 if (r < 0)
1429                         return r;
1430         }
1431
1432         return 0;
1433 }
1434
1435 #define internal_match(bus, m)                                          \
1436         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1437          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1438          : (m))
1439
1440 static int bus_add_match_internal_dbus1(
1441                 sd_bus *bus,
1442                 const char *match) {
1443
1444         const char *e;
1445
1446         assert(bus);
1447         assert(match);
1448
1449         e = internal_match(bus, match);
1450
1451         return sd_bus_call_method(
1452                         bus,
1453                         "org.freedesktop.DBus",
1454                         "/org/freedesktop/DBus",
1455                         "org.freedesktop.DBus",
1456                         "AddMatch",
1457                         NULL,
1458                         NULL,
1459                         "s",
1460                         e);
1461 }
1462
1463 int bus_add_match_internal(
1464                 sd_bus *bus,
1465                 const char *match,
1466                 struct bus_match_component *components,
1467                 unsigned n_components,
1468                 uint64_t cookie) {
1469
1470         assert(bus);
1471
1472         if (!bus->bus_client)
1473                 return -EINVAL;
1474
1475         if (bus->is_kernel)
1476                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1477         else
1478                 return bus_add_match_internal_dbus1(bus, match);
1479 }
1480
1481 int bus_remove_match_internal_kernel(
1482                 sd_bus *bus,
1483                 uint64_t cookie) {
1484
1485         struct kdbus_cmd_match m = {
1486                 .size = offsetof(struct kdbus_cmd_match, items),
1487                 .cookie = cookie,
1488         };
1489         int r;
1490
1491         assert(bus);
1492
1493         /* Monitor streams don't support matches, make this a NOP */
1494         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1495                 return 0;
1496
1497         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1498         if (r < 0)
1499                 return -errno;
1500
1501         return 0;
1502 }
1503
1504 static int bus_remove_match_internal_dbus1(
1505                 sd_bus *bus,
1506                 const char *match) {
1507
1508         const char *e;
1509
1510         assert(bus);
1511         assert(match);
1512
1513         e = internal_match(bus, match);
1514
1515         return sd_bus_call_method(
1516                         bus,
1517                         "org.freedesktop.DBus",
1518                         "/org/freedesktop/DBus",
1519                         "org.freedesktop.DBus",
1520                         "RemoveMatch",
1521                         NULL,
1522                         NULL,
1523                         "s",
1524                         e);
1525 }
1526
1527 int bus_remove_match_internal(
1528                 sd_bus *bus,
1529                 const char *match,
1530                 uint64_t cookie) {
1531
1532         assert(bus);
1533
1534         if (!bus->bus_client)
1535                 return -EINVAL;
1536
1537         if (bus->is_kernel)
1538                 return bus_remove_match_internal_kernel(bus, cookie);
1539         else
1540                 return bus_remove_match_internal_dbus1(bus, match);
1541 }
1542
1543 #if 0 /// UNNEEDED by elogind
1544 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1545         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
1546         const char *mid;
1547         int r;
1548
1549         assert_return(bus, -EINVAL);
1550         assert_return(name, -EINVAL);
1551         assert_return(machine, -EINVAL);
1552         assert_return(!bus_pid_changed(bus), -ECHILD);
1553         assert_return(service_name_is_valid(name), -EINVAL);
1554
1555         if (!bus->bus_client)
1556                 return -EINVAL;
1557
1558         if (!BUS_IS_OPEN(bus->state))
1559                 return -ENOTCONN;
1560
1561         if (streq_ptr(name, bus->unique_name))
1562                 return sd_id128_get_machine(machine);
1563
1564         r = sd_bus_message_new_method_call(
1565                         bus,
1566                         &m,
1567                         name,
1568                         "/",
1569                         "org.freedesktop.DBus.Peer",
1570                         "GetMachineId");
1571         if (r < 0)
1572                 return r;
1573
1574         r = sd_bus_message_set_auto_start(m, false);
1575         if (r < 0)
1576                 return r;
1577
1578         r = sd_bus_call(bus, m, 0, NULL, &reply);
1579         if (r < 0)
1580                 return r;
1581
1582         r = sd_bus_message_read(reply, "s", &mid);
1583         if (r < 0)
1584                 return r;
1585
1586         return sd_id128_from_string(mid, machine);
1587 }
1588 #endif // 0