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