chiark / gitweb /
sd-bus: fix an assert when running in kdbus mode
[elogind.git] / src / libsystemd / sd-bus / bus-control.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
24 #endif
25
26 #include <stddef.h>
27 #include <errno.h>
28
29 #include "strv.h"
30 #include "sd-bus.h"
31 #include "bus-internal.h"
32 #include "bus-message.h"
33 #include "bus-control.h"
34 #include "bus-bloom.h"
35 #include "bus-util.h"
36 #include "cgroup-util.h"
37
38 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
39         int r;
40
41         assert_return(bus, -EINVAL);
42         assert_return(unique, -EINVAL);
43         assert_return(!bus_pid_changed(bus), -ECHILD);
44
45         r = bus_ensure_running(bus);
46         if (r < 0)
47                 return r;
48
49         *unique = bus->unique_name;
50         return 0;
51 }
52
53 static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
54         struct kdbus_cmd_name *n;
55         size_t size, l;
56         int r;
57
58         assert(bus);
59         assert(name);
60
61         l = strlen(name);
62         size = offsetof(struct kdbus_cmd_name, name) + l + 1;
63         n = alloca0(size);
64         n->size = size;
65         kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
66         memcpy(n->name, name, l+1);
67
68 #ifdef HAVE_VALGRIND_MEMCHECK_H
69         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
70 #endif
71
72         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
73         if (r < 0)
74                 return -errno;
75
76         if (n->flags & KDBUS_NAME_IN_QUEUE)
77                 return 0;
78
79         return 1;
80 }
81
82 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
83         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
84         uint32_t ret, param = 0;
85         int r;
86
87         assert(bus);
88         assert(name);
89
90         if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
91                 param |= BUS_NAME_ALLOW_REPLACEMENT;
92         if (flags & SD_BUS_NAME_REPLACE_EXISTING)
93                 param |= BUS_NAME_REPLACE_EXISTING;
94         if (!(flags & SD_BUS_NAME_QUEUE))
95                 param |= BUS_NAME_DO_NOT_QUEUE;
96
97         r = sd_bus_call_method(
98                         bus,
99                         "org.freedesktop.DBus",
100                         "/org/freedesktop/DBus",
101                         "org.freedesktop.DBus",
102                         "RequestName",
103                         NULL,
104                         &reply,
105                         "su",
106                         name,
107                         param);
108         if (r < 0)
109                 return r;
110
111         r = sd_bus_message_read(reply, "u", &ret);
112         if (r < 0)
113                 return r;
114
115         if (ret == BUS_NAME_ALREADY_OWNER)
116                 return -EALREADY;
117         else if (ret == BUS_NAME_EXISTS)
118                 return -EEXIST;
119         else if (ret == BUS_NAME_IN_QUEUE)
120                 return 0;
121         else if (ret == BUS_NAME_PRIMARY_OWNER)
122                 return 1;
123
124         return -EIO;
125 }
126
127 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
128         assert_return(bus, -EINVAL);
129         assert_return(name, -EINVAL);
130         assert_return(bus->bus_client, -EINVAL);
131         assert_return(!bus_pid_changed(bus), -ECHILD);
132         assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
133         assert_return(service_name_is_valid(name), -EINVAL);
134         assert_return(name[0] != ':', -EINVAL);
135
136         if (!BUS_IS_OPEN(bus->state))
137                 return -ENOTCONN;
138
139         if (bus->is_kernel)
140                 return bus_request_name_kernel(bus, name, flags);
141         else
142                 return bus_request_name_dbus1(bus, name, flags);
143 }
144
145 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
146         struct kdbus_cmd_name *n;
147         size_t l;
148         int r;
149
150         assert(bus);
151         assert(name);
152
153         l = strlen(name);
154         n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
155         n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
156         memcpy(n->name, name, l+1);
157
158 #ifdef HAVE_VALGRIND_MEMCHECK_H
159         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
160 #endif
161         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
162         if (r < 0)
163                 return -errno;
164
165         return n->flags;
166 }
167
168 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
169         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
170         uint32_t ret;
171         int r;
172
173         assert(bus);
174         assert(name);
175
176         r = sd_bus_call_method(
177                         bus,
178                         "org.freedesktop.DBus",
179                         "/org/freedesktop/DBus",
180                         "org.freedesktop.DBus",
181                         "ReleaseName",
182                         NULL,
183                         &reply,
184                         "s",
185                         name);
186         if (r < 0)
187                 return r;
188
189         r = sd_bus_message_read(reply, "u", &ret);
190         if (r < 0)
191                 return r;
192         if (ret == BUS_NAME_NON_EXISTENT)
193                 return -ESRCH;
194         if (ret == BUS_NAME_NOT_OWNER)
195                 return -EADDRINUSE;
196         if (ret == BUS_NAME_RELEASED)
197                 return 0;
198
199         return -EINVAL;
200 }
201
202 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
203         assert_return(bus, -EINVAL);
204         assert_return(name, -EINVAL);
205         assert_return(bus->bus_client, -EINVAL);
206         assert_return(!bus_pid_changed(bus), -ECHILD);
207         assert_return(service_name_is_valid(name), -EINVAL);
208         assert_return(name[0] != ':', -EINVAL);
209
210         if (!BUS_IS_OPEN(bus->state))
211                 return -ENOTCONN;
212
213         if (bus->is_kernel)
214                 return bus_release_name_kernel(bus, name);
215         else
216                 return bus_release_name_dbus1(bus, name);
217 }
218
219 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
220         struct kdbus_cmd_name_list cmd = {};
221         struct kdbus_name_list *name_list;
222         struct kdbus_cmd_name *name;
223         uint64_t previous_id = 0;
224         int r;
225
226         /* Caller will free half-constructed list on failure... */
227
228         cmd.flags = flags;
229
230         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
231         if (r < 0)
232                 return -errno;
233
234         name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
235
236         KDBUS_ITEM_FOREACH(name, name_list, names) {
237
238                 if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
239                         char *n;
240
241                         if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0)
242                                 return -ENOMEM;
243
244                         r = strv_consume(x, n);
245                         if (r < 0)
246                                 return r;
247
248                         previous_id = name->owner_id;
249                 }
250
251                 if (name->size > sizeof(*name) && service_name_is_valid(name->name)) {
252                         r = strv_extend(x, name->name);
253                         if (r < 0)
254                                 return -ENOMEM;
255                 }
256         }
257
258         r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd.offset);
259         if (r < 0)
260                 return -errno;
261
262         return 0;
263 }
264
265 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
266         _cleanup_strv_free_ char **x = NULL, **y = NULL;
267         int r;
268
269         if (acquired) {
270                 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
271                 if (r < 0)
272                         return r;
273         }
274
275         if (activatable) {
276                 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
277                 if (r < 0)
278                         return r;
279
280                 *activatable = y;
281                 y = NULL;
282         }
283
284         if (acquired) {
285                 *acquired = x;
286                 x = NULL;
287         }
288
289         return 0;
290 }
291
292 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
293         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
294         _cleanup_strv_free_ char **x = NULL, **y = NULL;
295         int r;
296
297         if (acquired) {
298                 r = sd_bus_call_method(
299                                 bus,
300                                 "org.freedesktop.DBus",
301                                 "/org/freedesktop/DBus",
302                                 "org.freedesktop.DBus",
303                                 "ListNames",
304                                 NULL,
305                                 &reply,
306                                 NULL);
307                 if (r < 0)
308                         return r;
309
310                 r = sd_bus_message_read_strv(reply, &x);
311                 if (r < 0)
312                         return r;
313
314                 reply = sd_bus_message_unref(reply);
315         }
316
317         if (activatable) {
318                 r = sd_bus_call_method(
319                                 bus,
320                                 "org.freedesktop.DBus",
321                                 "/org/freedesktop/DBus",
322                                 "org.freedesktop.DBus",
323                                 "ListActivatableNames",
324                                 NULL,
325                                 &reply,
326                                 NULL);
327                 if (r < 0)
328                         return r;
329
330                 r = sd_bus_message_read_strv(reply, &y);
331                 if (r < 0)
332                         return r;
333
334                 *activatable = y;
335                 y = NULL;
336         }
337
338         if (acquired) {
339                 *acquired = x;
340                 x = NULL;
341         }
342
343         return 0;
344 }
345
346 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
347         assert_return(bus, -EINVAL);
348         assert_return(acquired || activatable, -EINVAL);
349         assert_return(!bus_pid_changed(bus), -ECHILD);
350
351         if (!BUS_IS_OPEN(bus->state))
352                 return -ENOTCONN;
353
354         if (bus->is_kernel)
355                 return bus_list_names_kernel(bus, acquired, activatable);
356         else
357                 return bus_list_names_dbus1(bus, acquired, activatable);
358 }
359
360 static int bus_get_owner_kdbus(
361                 sd_bus *bus,
362                 const char *name,
363                 uint64_t mask,
364                 sd_bus_creds **creds) {
365
366         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
367         struct kdbus_cmd_conn_info *cmd;
368         struct kdbus_conn_info *conn_info;
369         struct kdbus_item *item;
370         size_t size;
371         uint64_t m, id;
372         int r;
373
374         r = bus_kernel_parse_unique_name(name, &id);
375         if (r < 0)
376                 return r;
377         if (r > 0) {
378                 size = offsetof(struct kdbus_cmd_conn_info, name);
379                 cmd = alloca0(size);
380                 cmd->id = id;
381         } else {
382                 size = offsetof(struct kdbus_cmd_conn_info, name) + strlen(name) + 1;
383                 cmd = alloca0(size);
384                 strcpy(cmd->name, name);
385         }
386
387         cmd->size = size;
388         kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
389
390         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
391         if (r < 0)
392                 return -errno;
393
394         conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
395
396         /* Non-activated names are considered not available */
397         if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
398                 return name[0] == ':' ? -ENXIO : -ESRCH;
399
400         c = bus_creds_new();
401         if (!c)
402                 return -ENOMEM;
403
404         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
405                 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
406                         return -ENOMEM;
407
408                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
409         }
410
411         KDBUS_ITEM_FOREACH(item, conn_info, items) {
412
413                 switch (item->type) {
414
415                 case KDBUS_ITEM_CREDS:
416                         m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
417
418                         if (m) {
419                                 c->uid = (uid_t) item->creds.uid;
420                                 c->pid = (pid_t) item->creds.pid;
421                                 c->gid = (gid_t) item->creds.gid;
422                                 c->mask |= m;
423                         }
424
425                         if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
426                                 c->tid = (pid_t) item->creds.tid;
427                                 c->mask |= SD_BUS_CREDS_TID;
428                         }
429
430                         if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
431                                 c->pid_starttime = item->creds.starttime;
432                                 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
433                         }
434
435                         break;
436
437                 case KDBUS_ITEM_PID_COMM:
438                         if (mask & SD_BUS_CREDS_COMM) {
439                                 c->comm = strdup(item->str);
440                                 if (!c->comm) {
441                                         r = -ENOMEM;
442                                         goto fail;
443                                 }
444
445                                 c->mask |= SD_BUS_CREDS_COMM;
446                         }
447                         break;
448
449                 case KDBUS_ITEM_TID_COMM:
450                         if (mask & SD_BUS_CREDS_TID_COMM) {
451                                 c->tid_comm = strdup(item->str);
452                                 if (!c->tid_comm) {
453                                         r = -ENOMEM;
454                                         goto fail;
455                                 }
456
457                                 c->mask |= SD_BUS_CREDS_TID_COMM;
458                         }
459                         break;
460
461                 case KDBUS_ITEM_EXE:
462                         if (mask & SD_BUS_CREDS_EXE) {
463                                 c->exe = strdup(item->str);
464                                 if (!c->exe) {
465                                         r = -ENOMEM;
466                                         goto fail;
467                                 }
468
469                                 c->mask |= SD_BUS_CREDS_EXE;
470                         }
471                         break;
472
473                 case KDBUS_ITEM_CMDLINE:
474                         if (mask & SD_BUS_CREDS_CMDLINE) {
475                                 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
476                                 c->cmdline = memdup(item->data, c->cmdline_size);
477                                 if (!c->cmdline) {
478                                         r = -ENOMEM;
479                                         goto fail;
480                                 }
481
482                                 c->mask |= SD_BUS_CREDS_CMDLINE;
483                         }
484                         break;
485
486                 case KDBUS_ITEM_CGROUP:
487                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
488                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
489                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
490
491                         if (m) {
492                                 c->cgroup = strdup(item->str);
493                                 if (!c->cgroup) {
494                                         r = -ENOMEM;
495                                         goto fail;
496                                 }
497
498                                 if (!bus->cgroup_root) {
499                                         r = cg_get_root_path(&bus->cgroup_root);
500                                         if (r < 0)
501                                                 goto fail;
502                                 }
503
504                                 c->cgroup_root = strdup(bus->cgroup_root);
505                                 if (!c->cgroup_root) {
506                                         r = -ENOMEM;
507                                         goto fail;
508                                 }
509
510                                 c->mask |= m;
511                         }
512                         break;
513
514                 case KDBUS_ITEM_CAPS:
515                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
516                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
517
518                         if (m) {
519                                 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
520                                 c->capability = memdup(item->data, c->capability_size);
521                                 if (!c->capability) {
522                                         r = -ENOMEM;
523                                         goto fail;
524                                 }
525
526                                 c->mask |= m;
527                         }
528                         break;
529
530                 case KDBUS_ITEM_SECLABEL:
531                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
532                                 c->label = strdup(item->str);
533                                 if (!c->label) {
534                                         r = -ENOMEM;
535                                         goto fail;
536                                 }
537
538                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
539                         }
540                         break;
541
542                 case KDBUS_ITEM_AUDIT:
543                         m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
544
545                         if (m) {
546                                 c->audit_session_id = item->audit.sessionid;
547                                 c->audit_login_uid = item->audit.loginuid;
548                                 c->mask |= m;
549                         }
550                         break;
551
552                 case KDBUS_ITEM_NAME:
553                         if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
554                                 r = strv_extend(&c->well_known_names, item->name.name);
555                                 if (r < 0)
556                                         goto fail;
557
558                                 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
559                         }
560                         break;
561
562                 case KDBUS_ITEM_CONN_NAME:
563                         if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
564                                 c->conn_name = strdup(item->str);
565                                 if (!c->conn_name) {
566                                         r = -ENOMEM;
567                                         goto fail;
568                                 }
569
570                                 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
571                         }
572                         break;
573                 }
574         }
575
576         if (creds) {
577                 *creds = c;
578                 c = NULL;
579         }
580
581         r = 0;
582
583 fail:
584         ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
585         return r;
586 }
587
588 static int bus_get_owner_dbus1(
589                 sd_bus *bus,
590                 const char *name,
591                 uint64_t mask,
592                 sd_bus_creds **creds) {
593
594         _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
595         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
596         const char *unique = NULL;
597         pid_t pid = 0;
598         int r;
599
600         /* Only query the owner if the caller wants to know it or if
601          * the caller just wants to check whether a name exists */
602         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
603                 r = sd_bus_call_method(
604                                 bus,
605                                 "org.freedesktop.DBus",
606                                 "/org/freedesktop/DBus",
607                                 "org.freedesktop.DBus",
608                                 "GetNameOwner",
609                                 NULL,
610                                 &reply_unique,
611                                 "s",
612                                 name);
613                 if (r < 0)
614                         return r;
615
616                 r = sd_bus_message_read(reply_unique, "s", &unique);
617                 if (r < 0)
618                         return r;
619         }
620
621         if (mask != 0) {
622                 c = bus_creds_new();
623                 if (!c)
624                         return -ENOMEM;
625
626                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
627                         c->unique_name = strdup(unique);
628                         if (!c->unique_name)
629                                 return -ENOMEM;
630
631                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
632                 }
633
634                 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
635                             SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
636                             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|
637                             SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
638                             SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
639                         uint32_t u;
640
641                         r = sd_bus_call_method(
642                                         bus,
643                                         "org.freedesktop.DBus",
644                                         "/org/freedesktop/DBus",
645                                         "org.freedesktop.DBus",
646                                         "GetConnectionUnixProcessID",
647                                         NULL,
648                                         &reply,
649                                         "s",
650                                         unique ? unique : name);
651                         if (r < 0)
652                                 return r;
653
654                         r = sd_bus_message_read(reply, "u", &u);
655                         if (r < 0)
656                                 return r;
657
658                         pid = u;
659                         if (mask & SD_BUS_CREDS_PID) {
660                                 c->pid = u;
661                                 c->mask |= SD_BUS_CREDS_PID;
662                         }
663
664                         reply = sd_bus_message_unref(reply);
665                 }
666
667                 if (mask & SD_BUS_CREDS_UID) {
668                         uint32_t u;
669
670                         r = sd_bus_call_method(
671                                         bus,
672                                         "org.freedesktop.DBus",
673                                         "/org/freedesktop/DBus",
674                                         "org.freedesktop.DBus",
675                                         "GetConnectionUnixUser",
676                                         NULL,
677                                         &reply,
678                                         "s",
679                                         unique ? unique : name);
680                         if (r < 0)
681                                 return r;
682
683                         r = sd_bus_message_read(reply, "u", &u);
684                         if (r < 0)
685                                 return r;
686
687                         c->uid = u;
688                         c->mask |= SD_BUS_CREDS_UID;
689
690                         reply = sd_bus_message_unref(reply);
691                 }
692
693                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
694                         const void *p = NULL;
695                         size_t sz = 0;
696
697                         r = sd_bus_call_method(
698                                         bus,
699                                         "org.freedesktop.DBus",
700                                         "/org/freedesktop/DBus",
701                                         "org.freedesktop.DBus",
702                                         "GetConnectionSELinuxSecurityContext",
703                                         NULL,
704                                         &reply,
705                                         "s",
706                                         unique ? unique : name);
707                         if (r < 0)
708                                 return r;
709
710                         r = sd_bus_message_read_array(reply, 'y', &p, &sz);
711                         if (r < 0)
712                                 return r;
713
714                         c->label = strndup(p, sz);
715                         if (!c->label)
716                                 return -ENOMEM;
717
718                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
719                 }
720
721                 r = bus_creds_add_more(c, mask, pid, 0);
722                 if (r < 0)
723                         return r;
724         }
725
726         if (creds) {
727                 *creds = c;
728                 c = NULL;
729         }
730
731         return 0;
732 }
733
734 _public_ int sd_bus_get_owner(
735                 sd_bus *bus,
736                 const char *name,
737                 uint64_t mask,
738                 sd_bus_creds **creds) {
739
740         assert_return(bus, -EINVAL);
741         assert_return(name, -EINVAL);
742         assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
743         assert_return(mask == 0 || creds, -EINVAL);
744         assert_return(!bus_pid_changed(bus), -ECHILD);
745         assert_return(service_name_is_valid(name), -EINVAL);
746         assert_return(bus->bus_client, -ENODATA);
747
748         if (!BUS_IS_OPEN(bus->state))
749                 return -ENOTCONN;
750
751         if (bus->is_kernel)
752                 return bus_get_owner_kdbus(bus, name, mask, creds);
753         else
754                 return bus_get_owner_dbus1(bus, name, mask, creds);
755 }
756
757 static int add_name_change_match(sd_bus *bus,
758                                  uint64_t cookie,
759                                  const char *name,
760                                  const char *old_owner,
761                                  const char *new_owner) {
762
763         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
764         int is_name_id = -1, r;
765         struct kdbus_item *item;
766
767         assert(bus);
768
769         /* If we encounter a match that could match against
770          * NameOwnerChanged messages, then we need to create
771          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
772          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
773          * multiple if the match is underspecified.
774          *
775          * The NameOwnerChanged signals take three parameters with
776          * unique or well-known names, but only some forms actually
777          * exist:
778          *
779          * WELLKNOWN, "", UNIQUE       → KDBUS_ITEM_NAME_ADD
780          * WELLKNOWN, UNIQUE, ""       → KDBUS_ITEM_NAME_REMOVE
781          * WELLKNOWN, UNIQUE, UNIQUE   → KDBUS_ITEM_NAME_CHANGE
782          * UNIQUE, "", UNIQUE          → KDBUS_ITEM_ID_ADD
783          * UNIQUE, UNIQUE, ""          → KDBUS_ITEM_ID_REMOVE
784          *
785          * For the latter two the two unique names must be identical.
786          *
787          * */
788
789         if (name) {
790                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
791                 if (is_name_id < 0)
792                         return 0;
793         }
794
795         if (!isempty(old_owner)) {
796                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
797                 if (r < 0)
798                         return 0;
799                 if (r == 0)
800                         return 0;
801                 if (is_name_id > 0 && old_owner_id != name_id)
802                         return 0;
803         } else
804                 old_owner_id = KDBUS_MATCH_ID_ANY;
805
806         if (!isempty(new_owner)) {
807                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
808                 if (r < 0)
809                         return r;
810                 if (r == 0)
811                         return 0;
812                 if (is_name_id > 0 && new_owner_id != name_id)
813                         return 0;
814         } else
815                 new_owner_id = KDBUS_MATCH_ID_ANY;
816
817         if (is_name_id <= 0) {
818                 struct kdbus_cmd_match *m;
819                 size_t sz, l;
820
821                 /* If the name argument is missing or is a well-known
822                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
823                  * matches for it */
824
825                 l = name ? strlen(name) + 1 : 0;
826
827                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
828                             offsetof(struct kdbus_item, name_change) +
829                             offsetof(struct kdbus_notify_name_change, name) +
830                             l);
831
832                 m = alloca0(sz);
833                 m->size = sz;
834                 m->cookie = cookie;
835
836                 item = m->items;
837                 item->size =
838                         offsetof(struct kdbus_item, name_change) +
839                         offsetof(struct kdbus_notify_name_change, name) +
840                         l;
841
842                 item->name_change.old.id = old_owner_id;
843                 item->name_change.new.id = new_owner_id;
844
845                 if (name)
846                         memcpy(item->name_change.name, name, l);
847
848                 /* If the old name is unset or empty, then
849                  * this can match against added names */
850                 if (!old_owner || old_owner[0] == 0) {
851                         item->type = KDBUS_ITEM_NAME_ADD;
852
853                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
854                         if (r < 0)
855                                 return -errno;
856                 }
857
858                 /* If the new name is unset or empty, then
859                  * this can match against removed names */
860                 if (!new_owner || new_owner[0] == 0) {
861                         item->type = KDBUS_ITEM_NAME_REMOVE;
862
863                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
864                         if (r < 0)
865                                 return -errno;
866                 }
867
868                 /* The CHANGE match we need in either case, because
869                  * what is reported as a name change by the kernel
870                  * might just be an owner change between starter and
871                  * normal clients. For userspace such a change should
872                  * be considered a removal/addition, hence let's
873                  * subscribe to this unconditionally. */
874                 item->type = KDBUS_ITEM_NAME_CHANGE;
875                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
876                 if (r < 0)
877                         return -errno;
878         }
879
880         if (is_name_id != 0) {
881                 struct kdbus_cmd_match *m;
882                 uint64_t sz;
883
884                 /* If the name argument is missing or is a unique
885                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
886                  * for it */
887
888                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
889                             offsetof(struct kdbus_item, id_change) +
890                             sizeof(struct kdbus_notify_id_change));
891
892                 m = alloca0(sz);
893                 m->size = sz;
894                 m->cookie = cookie;
895
896                 item = m->items;
897                 item->size =
898                         offsetof(struct kdbus_item, id_change) +
899                         sizeof(struct kdbus_notify_id_change);
900                 item->id_change.id = name_id;
901
902                 /* If the old name is unset or empty, then this can
903                  * match against added ids */
904                 if (!old_owner || old_owner[0] == 0) {
905                         item->type = KDBUS_ITEM_ID_ADD;
906
907                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
908                         if (r < 0)
909                                 return -errno;
910                 }
911
912                 /* If thew new name is unset or empty, then this can
913                  * match against removed ids */
914                 if (!new_owner || new_owner[0] == 0) {
915                         item->type = KDBUS_ITEM_ID_REMOVE;
916
917                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
918                         if (r < 0)
919                                 return -errno;
920                 }
921         }
922
923         return 0;
924 }
925
926 int bus_add_match_internal_kernel(
927                 sd_bus *bus,
928                 struct bus_match_component *components,
929                 unsigned n_components,
930                 uint64_t cookie) {
931
932         struct kdbus_cmd_match *m;
933         struct kdbus_item *item;
934         uint64_t *bloom;
935         size_t sz;
936         const char *sender = NULL;
937         size_t sender_length = 0;
938         uint64_t src_id = KDBUS_MATCH_ID_ANY;
939         bool using_bloom = false;
940         unsigned i;
941         bool matches_name_change = true;
942         const char *name_change_arg[3] = {};
943         int r;
944
945         assert(bus);
946
947         bloom = alloca0(bus->bloom_size);
948
949         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
950
951         for (i = 0; i < n_components; i++) {
952                 struct bus_match_component *c = &components[i];
953
954                 switch (c->type) {
955
956                 case BUS_MATCH_SENDER:
957                         if (!streq(c->value_str, "org.freedesktop.DBus"))
958                                 matches_name_change = false;
959
960                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
961                         if (r < 0)
962                                 return r;
963                         else if (r > 0)
964                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
965                         else  {
966                                 sender = c->value_str;
967                                 sender_length = strlen(sender);
968                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
969                         }
970
971                         break;
972
973                 case BUS_MATCH_MESSAGE_TYPE:
974                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
975                                 matches_name_change = false;
976
977                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
978                         using_bloom = true;
979                         break;
980
981                 case BUS_MATCH_INTERFACE:
982                         if (!streq(c->value_str, "org.freedesktop.DBus"))
983                                 matches_name_change = false;
984
985                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
986                         using_bloom = true;
987                         break;
988
989                 case BUS_MATCH_MEMBER:
990                         if (!streq(c->value_str, "NameOwnerChanged"))
991                                 matches_name_change = false;
992
993                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
994                         using_bloom = true;
995                         break;
996
997                 case BUS_MATCH_PATH:
998                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
999                                 matches_name_change = false;
1000
1001                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1002                         using_bloom = true;
1003                         break;
1004
1005                 case BUS_MATCH_PATH_NAMESPACE:
1006                         if (!streq(c->value_str, "/")) {
1007                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1008                                 using_bloom = true;
1009                         }
1010                         break;
1011
1012                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1013                         char buf[sizeof("arg")-1 + 2 + 1];
1014
1015                         if (c->type - BUS_MATCH_ARG < 3)
1016                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1017
1018                         snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1019                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1020                         using_bloom = true;
1021                         break;
1022                 }
1023
1024                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1025                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1026
1027                         snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1028                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1029                         using_bloom = true;
1030                         break;
1031                 }
1032
1033                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1034                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1035
1036                         snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1037                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1038                         using_bloom = true;
1039                         break;
1040                 }
1041
1042                 case BUS_MATCH_DESTINATION:
1043                         /* The bloom filter does not include
1044                            the destination, since it is only
1045                            available for broadcast messages
1046                            which do not carry a destination
1047                            since they are undirected. */
1048                         break;
1049
1050                 case BUS_MATCH_ROOT:
1051                 case BUS_MATCH_VALUE:
1052                 case BUS_MATCH_LEAF:
1053                 case _BUS_MATCH_NODE_TYPE_MAX:
1054                 case _BUS_MATCH_NODE_TYPE_INVALID:
1055                         assert_not_reached("Invalid match type?");
1056                 }
1057         }
1058
1059         if (using_bloom)
1060                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1061
1062         m = alloca0(sz);
1063         m->size = sz;
1064         m->cookie = cookie;
1065
1066         item = m->items;
1067
1068         if (src_id != KDBUS_MATCH_ID_ANY) {
1069                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1070                 item->type = KDBUS_ITEM_ID;
1071                 item->id = src_id;
1072                 item = KDBUS_ITEM_NEXT(item);
1073         }
1074
1075         if (using_bloom) {
1076                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1077                 item->type = KDBUS_ITEM_BLOOM_MASK;
1078                 memcpy(item->data64, bloom, bus->bloom_size);
1079                 item = KDBUS_ITEM_NEXT(item);
1080         }
1081
1082         if (sender) {
1083                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1084                 item->type = KDBUS_ITEM_NAME;
1085                 memcpy(item->str, sender, sender_length + 1);
1086         }
1087
1088         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1089         if (r < 0)
1090                 return -errno;
1091
1092         if (matches_name_change) {
1093
1094                 /* If this match could theoretically match
1095                  * NameOwnerChanged messages, we need to
1096                  * install a second non-bloom filter explitly
1097                  * for it */
1098
1099                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1100                 if (r < 0)
1101                         return r;
1102         }
1103
1104         return 0;
1105 }
1106
1107 #define internal_match(bus, m)                                          \
1108         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1109          ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1110          : (m))
1111
1112 static int bus_add_match_internal_dbus1(
1113                 sd_bus *bus,
1114                 const char *match) {
1115
1116         const char *e;
1117
1118         assert(bus);
1119         assert(match);
1120
1121         e = internal_match(bus, match);
1122
1123         return sd_bus_call_method(
1124                         bus,
1125                         "org.freedesktop.DBus",
1126                         "/org/freedesktop/DBus",
1127                         "org.freedesktop.DBus",
1128                         "AddMatch",
1129                         NULL,
1130                         NULL,
1131                         "s",
1132                         e);
1133 }
1134
1135 int bus_add_match_internal(
1136                 sd_bus *bus,
1137                 const char *match,
1138                 struct bus_match_component *components,
1139                 unsigned n_components,
1140                 uint64_t cookie) {
1141
1142         assert(bus);
1143
1144         if (bus->is_kernel)
1145                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1146         else
1147                 return bus_add_match_internal_dbus1(bus, match);
1148 }
1149
1150 int bus_remove_match_internal_kernel(
1151                 sd_bus *bus,
1152                 uint64_t cookie) {
1153
1154         struct kdbus_cmd_match m;
1155         int r;
1156
1157         assert(bus);
1158
1159         zero(m);
1160         m.size = offsetof(struct kdbus_cmd_match, items);
1161         m.cookie = cookie;
1162
1163         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1164         if (r < 0)
1165                 return -errno;
1166
1167         return 0;
1168 }
1169
1170 static int bus_remove_match_internal_dbus1(
1171                 sd_bus *bus,
1172                 const char *match) {
1173
1174         const char *e;
1175
1176         assert(bus);
1177         assert(match);
1178
1179         e = internal_match(bus, match);
1180
1181         return sd_bus_call_method(
1182                         bus,
1183                         "org.freedesktop.DBus",
1184                         "/org/freedesktop/DBus",
1185                         "org.freedesktop.DBus",
1186                         "RemoveMatch",
1187                         NULL,
1188                         NULL,
1189                         "s",
1190                         e);
1191 }
1192
1193 int bus_remove_match_internal(
1194                 sd_bus *bus,
1195                 const char *match,
1196                 uint64_t cookie) {
1197
1198         assert(bus);
1199
1200         if (bus->is_kernel)
1201                 return bus_remove_match_internal_kernel(bus, cookie);
1202         else
1203                 return bus_remove_match_internal_dbus1(bus, match);
1204 }
1205
1206 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1207         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1208         const char *mid;
1209         int r;
1210
1211         assert_return(bus, -EINVAL);
1212         assert_return(name, -EINVAL);
1213         assert_return(machine, -EINVAL);
1214         assert_return(!bus_pid_changed(bus), -ECHILD);
1215         assert_return(service_name_is_valid(name), -EINVAL);
1216
1217         if (!BUS_IS_OPEN(bus->state))
1218                 return -ENOTCONN;
1219
1220         if (streq_ptr(name, bus->unique_name))
1221                 return sd_id128_get_machine(machine);
1222
1223         r = sd_bus_message_new_method_call(
1224                         bus,
1225                         &m,
1226                         name,
1227                         "/",
1228                         "org.freedesktop.DBus.Peer",
1229                         "GetMachineId");
1230         if (r < 0)
1231                 return r;
1232
1233         r = sd_bus_message_set_auto_start(m, false);
1234         if (r < 0)
1235                 return r;
1236
1237         r = sd_bus_call(bus, m, 0, NULL, &reply);
1238         if (r < 0)
1239                 return r;
1240
1241         r = sd_bus_message_read(reply, "s", &mid);
1242         if (r < 0)
1243                 return r;
1244
1245         return sd_id128_from_string(mid, machine);
1246 }