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