chiark / gitweb /
sd-bus: silence format warnings in kdbus code (#6072)
[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                 c = bus_creds_new();
790                 if (!c)
791                         return -ENOMEM;
792
793                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
794                         c->unique_name = strdup(unique);
795                         if (!c->unique_name)
796                                 return -ENOMEM;
797
798                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
799                 }
800
801                 if ((mask & SD_BUS_CREDS_PID) ||
802                     ((mask & SD_BUS_CREDS_AUGMENT) &&
803                      (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
804                               SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
805                               SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
806                               SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
807                               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|
808                               SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
809                               SD_BUS_CREDS_SELINUX_CONTEXT|
810                               SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
811
812                         uint32_t u;
813
814                         r = sd_bus_call_method(
815                                         bus,
816                                         "org.freedesktop.DBus",
817                                         "/org/freedesktop/DBus",
818                                         "org.freedesktop.DBus",
819                                         "GetConnectionUnixProcessID",
820                                         NULL,
821                                         &reply,
822                                         "s",
823                                         unique ? unique : name);
824                         if (r < 0)
825                                 return r;
826
827                         r = sd_bus_message_read(reply, "u", &u);
828                         if (r < 0)
829                                 return r;
830
831                         pid = u;
832                         if (mask & SD_BUS_CREDS_PID) {
833                                 c->pid = u;
834                                 c->mask |= SD_BUS_CREDS_PID;
835                         }
836
837                         reply = sd_bus_message_unref(reply);
838                 }
839
840                 if (mask & SD_BUS_CREDS_EUID) {
841                         uint32_t u;
842
843                         r = sd_bus_call_method(
844                                         bus,
845                                         "org.freedesktop.DBus",
846                                         "/org/freedesktop/DBus",
847                                         "org.freedesktop.DBus",
848                                         "GetConnectionUnixUser",
849                                         NULL,
850                                         &reply,
851                                         "s",
852                                         unique ? unique : name);
853                         if (r < 0)
854                                 return r;
855
856                         r = sd_bus_message_read(reply, "u", &u);
857                         if (r < 0)
858                                 return r;
859
860                         c->euid = u;
861                         c->mask |= SD_BUS_CREDS_EUID;
862
863                         reply = sd_bus_message_unref(reply);
864                 }
865
866                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
867                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
868                         const void *p = NULL;
869                         size_t sz = 0;
870
871                         r = sd_bus_call_method(
872                                         bus,
873                                         "org.freedesktop.DBus",
874                                         "/org/freedesktop/DBus",
875                                         "org.freedesktop.DBus",
876                                         "GetConnectionSELinuxSecurityContext",
877                                         &error,
878                                         &reply,
879                                         "s",
880                                         unique ? unique : name);
881                         if (r < 0) {
882                                 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
883                                         return r;
884                         } else {
885                                 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
886                                 if (r < 0)
887                                         return r;
888
889                                 c->label = strndup(p, sz);
890                                 if (!c->label)
891                                         return -ENOMEM;
892
893                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
894                         }
895                 }
896
897                 r = bus_creds_add_more(c, mask, pid, 0);
898                 if (r < 0)
899                         return r;
900         }
901
902         if (creds) {
903                 *creds = c;
904                 c = NULL;
905         }
906
907         return 0;
908 }
909
910 _public_ int sd_bus_get_name_creds(
911                 sd_bus *bus,
912                 const char *name,
913                 uint64_t mask,
914                 sd_bus_creds **creds) {
915
916         assert_return(bus, -EINVAL);
917         assert_return(name, -EINVAL);
918         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
919         assert_return(mask == 0 || creds, -EINVAL);
920         assert_return(!bus_pid_changed(bus), -ECHILD);
921         assert_return(service_name_is_valid(name), -EINVAL);
922
923         if (!bus->bus_client)
924                 return -EINVAL;
925
926         if (streq(name, "org.freedesktop.DBus.Local"))
927                 return -EINVAL;
928
929         if (!BUS_IS_OPEN(bus->state))
930                 return -ENOTCONN;
931
932         if (bus->is_kernel)
933                 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
934         else
935                 return bus_get_name_creds_dbus1(bus, name, mask, creds);
936 }
937
938 static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
939         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
940         struct kdbus_cmd_info cmd = {
941                 .size = sizeof(struct kdbus_cmd_info),
942         };
943         struct kdbus_info *creator_info;
944         pid_t pid = 0;
945         int r;
946
947         c = bus_creds_new();
948         if (!c)
949                 return -ENOMEM;
950
951         /* If augmentation is on, and the bus doesn't didn't allow us
952          * to get the bits we want, then ask for the PID/TID so that we
953          * can read the rest from /proc. */
954         if ((mask & SD_BUS_CREDS_AUGMENT) &&
955             (mask & (SD_BUS_CREDS_PPID|
956                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
957                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
958                      SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
959                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
960                      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|
961                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
962                      SD_BUS_CREDS_SELINUX_CONTEXT|
963                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
964                 mask |= SD_BUS_CREDS_PID;
965
966         cmd.attach_flags = attach_flags_to_kdbus(mask);
967
968         r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
969         if (r < 0)
970                 return -errno;
971
972         creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
973
974         r = bus_populate_creds_from_items(bus, creator_info, mask, c);
975         bus_kernel_cmd_free(bus, cmd.offset);
976         if (r < 0)
977                 return r;
978
979         r = bus_creds_add_more(c, mask, pid, 0);
980         if (r < 0)
981                 return r;
982
983         *ret = c;
984         c = NULL;
985         return 0;
986 }
987
988 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
989         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
990         pid_t pid = 0;
991         bool do_label;
992         int r;
993
994         assert(bus);
995
996         do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
997
998         /* Avoid allocating anything if we have no chance of returning useful data */
999         if (!bus->ucred_valid && !do_label)
1000                 return -ENODATA;
1001
1002         c = bus_creds_new();
1003         if (!c)
1004                 return -ENOMEM;
1005
1006         if (bus->ucred_valid) {
1007                 if (bus->ucred.pid > 0) {
1008                         pid = c->pid = bus->ucred.pid;
1009                         c->mask |= SD_BUS_CREDS_PID & mask;
1010                 }
1011
1012                 if (bus->ucred.uid != UID_INVALID) {
1013                         c->euid = bus->ucred.uid;
1014                         c->mask |= SD_BUS_CREDS_EUID & mask;
1015                 }
1016
1017                 if (bus->ucred.gid != GID_INVALID) {
1018                         c->egid = bus->ucred.gid;
1019                         c->mask |= SD_BUS_CREDS_EGID & mask;
1020                 }
1021         }
1022
1023         if (do_label) {
1024                 c->label = strdup(bus->label);
1025                 if (!c->label)
1026                         return -ENOMEM;
1027
1028                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1029         }
1030
1031         r = bus_creds_add_more(c, mask, pid, 0);
1032         if (r < 0)
1033                 return r;
1034
1035         *ret = c;
1036         c = NULL;
1037         return 0;
1038 }
1039
1040 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
1041         assert_return(bus, -EINVAL);
1042         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
1043         assert_return(ret, -EINVAL);
1044         assert_return(!bus_pid_changed(bus), -ECHILD);
1045
1046         if (!BUS_IS_OPEN(bus->state))
1047                 return -ENOTCONN;
1048
1049         if (bus->is_kernel)
1050                 return bus_get_owner_creds_kdbus(bus, mask, ret);
1051         else
1052                 return bus_get_owner_creds_dbus1(bus, mask, ret);
1053 }
1054
1055 static int add_name_change_match(sd_bus *bus,
1056                                  uint64_t cookie,
1057                                  const char *name,
1058                                  const char *old_owner,
1059                                  const char *new_owner) {
1060
1061         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
1062         int is_name_id = -1, r;
1063         struct kdbus_item *item;
1064
1065         assert(bus);
1066
1067         /* If we encounter a match that could match against
1068          * NameOwnerChanged messages, then we need to create
1069          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1070          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1071          * multiple if the match is underspecified.
1072          *
1073          * The NameOwnerChanged signals take three parameters with
1074          * unique or well-known names, but only some forms actually
1075          * exist:
1076          *
1077          * WELLKNOWN, "", UNIQUE       → KDBUS_ITEM_NAME_ADD
1078          * WELLKNOWN, UNIQUE, ""       → KDBUS_ITEM_NAME_REMOVE
1079          * WELLKNOWN, UNIQUE, UNIQUE   → KDBUS_ITEM_NAME_CHANGE
1080          * UNIQUE, "", UNIQUE          → KDBUS_ITEM_ID_ADD
1081          * UNIQUE, UNIQUE, ""          → KDBUS_ITEM_ID_REMOVE
1082          *
1083          * For the latter two the two unique names must be identical.
1084          *
1085          * */
1086
1087         if (name) {
1088                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1089                 if (is_name_id < 0)
1090                         return 0;
1091         }
1092
1093         if (!isempty(old_owner)) {
1094                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1095                 if (r < 0)
1096                         return 0;
1097                 if (r == 0)
1098                         return 0;
1099                 if (is_name_id > 0 && old_owner_id != name_id)
1100                         return 0;
1101         } else
1102                 old_owner_id = KDBUS_MATCH_ID_ANY;
1103
1104         if (!isempty(new_owner)) {
1105                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1106                 if (r < 0)
1107                         return r;
1108                 if (r == 0)
1109                         return 0;
1110                 if (is_name_id > 0 && new_owner_id != name_id)
1111                         return 0;
1112         } else
1113                 new_owner_id = KDBUS_MATCH_ID_ANY;
1114
1115         if (is_name_id <= 0) {
1116                 struct kdbus_cmd_match *m;
1117                 size_t sz, l;
1118
1119                 /* If the name argument is missing or is a well-known
1120                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1121                  * matches for it */
1122
1123                 l = name ? strlen(name) + 1 : 0;
1124
1125                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1126                             offsetof(struct kdbus_item, name_change) +
1127                             offsetof(struct kdbus_notify_name_change, name) +
1128                             l);
1129
1130                 m = alloca0_align(sz, 8);
1131                 m->size = sz;
1132                 m->cookie = cookie;
1133
1134                 item = m->items;
1135                 item->size =
1136                         offsetof(struct kdbus_item, name_change) +
1137                         offsetof(struct kdbus_notify_name_change, name) +
1138                         l;
1139
1140                 item->name_change.old_id.id = old_owner_id;
1141                 item->name_change.new_id.id = new_owner_id;
1142
1143                 memcpy_safe(item->name_change.name, name, l);
1144
1145                 /* If the old name is unset or empty, then
1146                  * this can match against added names */
1147                 if (isempty(old_owner)) {
1148                         item->type = KDBUS_ITEM_NAME_ADD;
1149
1150                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1151                         if (r < 0)
1152                                 return -errno;
1153                 }
1154
1155                 /* If the new name is unset or empty, then
1156                  * this can match against removed names */
1157                 if (isempty(new_owner)) {
1158                         item->type = KDBUS_ITEM_NAME_REMOVE;
1159
1160                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1161                         if (r < 0)
1162                                 return -errno;
1163                 }
1164
1165                 /* The CHANGE match we need in either case, because
1166                  * what is reported as a name change by the kernel
1167                  * might just be an owner change between starter and
1168                  * normal clients. For userspace such a change should
1169                  * be considered a removal/addition, hence let's
1170                  * subscribe to this unconditionally. */
1171                 item->type = KDBUS_ITEM_NAME_CHANGE;
1172                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1173                 if (r < 0)
1174                         return -errno;
1175         }
1176
1177         if (is_name_id != 0) {
1178                 struct kdbus_cmd_match *m;
1179                 uint64_t sz;
1180
1181                 /* If the name argument is missing or is a unique
1182                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1183                  * for it */
1184
1185                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1186                             offsetof(struct kdbus_item, id_change) +
1187                             sizeof(struct kdbus_notify_id_change));
1188
1189                 m = alloca0_align(sz, 8);
1190                 m->size = sz;
1191                 m->cookie = cookie;
1192
1193                 item = m->items;
1194                 item->size =
1195                         offsetof(struct kdbus_item, id_change) +
1196                         sizeof(struct kdbus_notify_id_change);
1197                 item->id_change.id = name_id;
1198
1199                 /* If the old name is unset or empty, then this can
1200                  * match against added ids */
1201                 if (isempty(old_owner)) {
1202                         item->type = KDBUS_ITEM_ID_ADD;
1203                         if (!isempty(new_owner))
1204                                 item->id_change.id = new_owner_id;
1205
1206                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1207                         if (r < 0)
1208                                 return -errno;
1209                 }
1210
1211                 /* If thew new name is unset or empty, then this can
1212                  * match against removed ids */
1213                 if (isempty(new_owner)) {
1214                         item->type = KDBUS_ITEM_ID_REMOVE;
1215                         if (!isempty(old_owner))
1216                                 item->id_change.id = old_owner_id;
1217
1218                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1219                         if (r < 0)
1220                                 return -errno;
1221                 }
1222         }
1223
1224         return 0;
1225 }
1226
1227 int bus_add_match_internal_kernel(
1228                 sd_bus *bus,
1229                 struct bus_match_component *components,
1230                 unsigned n_components,
1231                 uint64_t cookie) {
1232
1233         struct kdbus_cmd_match *m;
1234         struct kdbus_item *item;
1235         uint64_t *bloom;
1236         size_t sz;
1237         const char *sender = NULL;
1238         size_t sender_length = 0;
1239         uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
1240         bool using_bloom = false;
1241         unsigned i;
1242         bool matches_name_change = true;
1243         const char *name_change_arg[3] = {};
1244         int r;
1245
1246         assert(bus);
1247
1248         /* Monitor streams don't support matches, make this a NOP */
1249         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1250                 return 0;
1251
1252         bloom = alloca0(bus->bloom_size);
1253
1254         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1255
1256         for (i = 0; i < n_components; i++) {
1257                 struct bus_match_component *c = &components[i];
1258
1259                 switch (c->type) {
1260
1261                 case BUS_MATCH_SENDER:
1262                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1263                                 matches_name_change = false;
1264
1265                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1266                         if (r < 0)
1267                                 return r;
1268                         else if (r > 0)
1269                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1270                         else  {
1271                                 sender = c->value_str;
1272                                 sender_length = strlen(sender);
1273                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1274                         }
1275
1276                         break;
1277
1278                 case BUS_MATCH_MESSAGE_TYPE:
1279                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1280                                 matches_name_change = false;
1281
1282                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1283                         using_bloom = true;
1284                         break;
1285
1286                 case BUS_MATCH_INTERFACE:
1287                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1288                                 matches_name_change = false;
1289
1290                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1291                         using_bloom = true;
1292                         break;
1293
1294                 case BUS_MATCH_MEMBER:
1295                         if (!streq(c->value_str, "NameOwnerChanged"))
1296                                 matches_name_change = false;
1297
1298                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1299                         using_bloom = true;
1300                         break;
1301
1302                 case BUS_MATCH_PATH:
1303                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1304                                 matches_name_change = false;
1305
1306                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1307                         using_bloom = true;
1308                         break;
1309
1310                 case BUS_MATCH_PATH_NAMESPACE:
1311                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1312                         using_bloom = true;
1313                         break;
1314
1315                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1316                         char buf[sizeof("arg")-1 + 2 + 1];
1317
1318                         if (c->type - BUS_MATCH_ARG < 3)
1319                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1320
1321                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1322                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1323                         using_bloom = true;
1324                         break;
1325                 }
1326
1327                 case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
1328                         char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
1329
1330                         xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
1331                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1332                         using_bloom = true;
1333                         break;
1334                 }
1335
1336                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
1337                         /*
1338                          * XXX: DBus spec defines arg[0..63]path= matching to be
1339                          * a two-way glob. That is, if either string is a prefix
1340                          * of the other, it matches.
1341                          * This is really hard to realize in bloom-filters, as
1342                          * we would have to create a bloom-match for each prefix
1343                          * of @c->value_str. This is excessive, hence we just
1344                          * ignore all those matches and accept everything from
1345                          * the kernel. People should really avoid those matches.
1346                          * If they're used in real-life some day, we will have
1347                          * to properly support multiple-matches here.
1348                          */
1349                         break;
1350
1351                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1352                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1353
1354                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1355                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1356                         using_bloom = true;
1357                         break;
1358                 }
1359
1360                 case BUS_MATCH_DESTINATION:
1361                         /*
1362                          * Kernel only supports matching on destination IDs, but
1363                          * not on destination names. So just skip the
1364                          * destination name restriction and verify it in
1365                          * user-space on retrieval.
1366                          */
1367                         r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
1368                         if (r < 0)
1369                                 return r;
1370                         else if (r > 0)
1371                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1372
1373                         /* if not a broadcast, it cannot be a name-change */
1374                         if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
1375                                 matches_name_change = false;
1376
1377                         break;
1378
1379                 case BUS_MATCH_ROOT:
1380                 case BUS_MATCH_VALUE:
1381                 case BUS_MATCH_LEAF:
1382                 case _BUS_MATCH_NODE_TYPE_MAX:
1383                 case _BUS_MATCH_NODE_TYPE_INVALID:
1384                         assert_not_reached("Invalid match type?");
1385                 }
1386         }
1387
1388         if (using_bloom)
1389                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1390
1391         m = alloca0_align(sz, 8);
1392         m->size = sz;
1393         m->cookie = cookie;
1394
1395         item = m->items;
1396
1397         if (src_id != KDBUS_MATCH_ID_ANY) {
1398                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1399                 item->type = KDBUS_ITEM_ID;
1400                 item->id = src_id;
1401                 item = KDBUS_ITEM_NEXT(item);
1402         }
1403
1404         if (dst_id != KDBUS_MATCH_ID_ANY) {
1405                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1406                 item->type = KDBUS_ITEM_DST_ID;
1407                 item->id = dst_id;
1408                 item = KDBUS_ITEM_NEXT(item);
1409         }
1410
1411         if (using_bloom) {
1412                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1413                 item->type = KDBUS_ITEM_BLOOM_MASK;
1414                 memcpy(item->data64, bloom, bus->bloom_size);
1415                 item = KDBUS_ITEM_NEXT(item);
1416         }
1417
1418         if (sender) {
1419                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1420                 item->type = KDBUS_ITEM_NAME;
1421                 memcpy(item->str, sender, sender_length + 1);
1422         }
1423
1424         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1425         if (r < 0)
1426                 return -errno;
1427
1428         if (matches_name_change) {
1429
1430                 /* If this match could theoretically match
1431                  * NameOwnerChanged messages, we need to
1432                  * install a second non-bloom filter explitly
1433                  * for it */
1434
1435                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1436                 if (r < 0)
1437                         return r;
1438         }
1439
1440         return 0;
1441 }
1442
1443 #define internal_match(bus, m)                                          \
1444         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1445          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1446          : (m))
1447
1448 static int bus_add_match_internal_dbus1(
1449                 sd_bus *bus,
1450                 const char *match) {
1451
1452         const char *e;
1453
1454         assert(bus);
1455         assert(match);
1456
1457         e = internal_match(bus, match);
1458
1459         return sd_bus_call_method(
1460                         bus,
1461                         "org.freedesktop.DBus",
1462                         "/org/freedesktop/DBus",
1463                         "org.freedesktop.DBus",
1464                         "AddMatch",
1465                         NULL,
1466                         NULL,
1467                         "s",
1468                         e);
1469 }
1470
1471 int bus_add_match_internal(
1472                 sd_bus *bus,
1473                 const char *match,
1474                 struct bus_match_component *components,
1475                 unsigned n_components,
1476                 uint64_t cookie) {
1477
1478         assert(bus);
1479
1480         if (!bus->bus_client)
1481                 return -EINVAL;
1482
1483         if (bus->is_kernel)
1484                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1485         else
1486                 return bus_add_match_internal_dbus1(bus, match);
1487 }
1488
1489 int bus_remove_match_internal_kernel(
1490                 sd_bus *bus,
1491                 uint64_t cookie) {
1492
1493         struct kdbus_cmd_match m = {
1494                 .size = offsetof(struct kdbus_cmd_match, items),
1495                 .cookie = cookie,
1496         };
1497         int r;
1498
1499         assert(bus);
1500
1501         /* Monitor streams don't support matches, make this a NOP */
1502         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1503                 return 0;
1504
1505         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1506         if (r < 0)
1507                 return -errno;
1508
1509         return 0;
1510 }
1511
1512 static int bus_remove_match_internal_dbus1(
1513                 sd_bus *bus,
1514                 const char *match) {
1515
1516         const char *e;
1517
1518         assert(bus);
1519         assert(match);
1520
1521         e = internal_match(bus, match);
1522
1523         return sd_bus_call_method(
1524                         bus,
1525                         "org.freedesktop.DBus",
1526                         "/org/freedesktop/DBus",
1527                         "org.freedesktop.DBus",
1528                         "RemoveMatch",
1529                         NULL,
1530                         NULL,
1531                         "s",
1532                         e);
1533 }
1534
1535 int bus_remove_match_internal(
1536                 sd_bus *bus,
1537                 const char *match,
1538                 uint64_t cookie) {
1539
1540         assert(bus);
1541
1542         if (!bus->bus_client)
1543                 return -EINVAL;
1544
1545         if (bus->is_kernel)
1546                 return bus_remove_match_internal_kernel(bus, cookie);
1547         else
1548                 return bus_remove_match_internal_dbus1(bus, match);
1549 }
1550
1551 #if 0 /// UNNEEDED by elogind
1552 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1553         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
1554         const char *mid;
1555         int r;
1556
1557         assert_return(bus, -EINVAL);
1558         assert_return(name, -EINVAL);
1559         assert_return(machine, -EINVAL);
1560         assert_return(!bus_pid_changed(bus), -ECHILD);
1561         assert_return(service_name_is_valid(name), -EINVAL);
1562
1563         if (!bus->bus_client)
1564                 return -EINVAL;
1565
1566         if (!BUS_IS_OPEN(bus->state))
1567                 return -ENOTCONN;
1568
1569         if (streq_ptr(name, bus->unique_name))
1570                 return sd_id128_get_machine(machine);
1571
1572         r = sd_bus_message_new_method_call(
1573                         bus,
1574                         &m,
1575                         name,
1576                         "/",
1577                         "org.freedesktop.DBus.Peer",
1578                         "GetMachineId");
1579         if (r < 0)
1580                 return r;
1581
1582         r = sd_bus_message_set_auto_start(m, false);
1583         if (r < 0)
1584                 return r;
1585
1586         r = sd_bus_call(bus, m, 0, NULL, &reply);
1587         if (r < 0)
1588                 return r;
1589
1590         r = sd_bus_message_read(reply, "s", &mid);
1591         if (r < 0)
1592                 return r;
1593
1594         return sd_id128_from_string(mid, machine);
1595 }
1596 #endif // 0