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