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