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