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