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