chiark / gitweb /
bd392a2937559902c9b295a8d2661b472eab82f1
[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 : -ENOENT;
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                 uint64_t id,
929                 struct bus_match_component *components,
930                 unsigned n_components,
931                 uint64_t cookie) {
932
933         struct kdbus_cmd_match *m;
934         struct kdbus_item *item;
935         uint64_t *bloom;
936         size_t sz;
937         const char *sender = NULL;
938         size_t sender_length = 0;
939         uint64_t src_id = KDBUS_MATCH_ID_ANY;
940         bool using_bloom = false;
941         unsigned i;
942         bool matches_name_change = true;
943         const char *name_change_arg[3] = {};
944         int r;
945
946         assert(bus);
947
948         bloom = alloca0(bus->bloom_size);
949
950         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
951
952         for (i = 0; i < n_components; i++) {
953                 struct bus_match_component *c = &components[i];
954
955                 switch (c->type) {
956
957                 case BUS_MATCH_SENDER:
958                         if (!streq(c->value_str, "org.freedesktop.DBus"))
959                                 matches_name_change = false;
960
961                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
962                         if (r < 0)
963                                 return r;
964                         else if (r > 0)
965                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
966                         else  {
967                                 sender = c->value_str;
968                                 sender_length = strlen(sender);
969                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
970                         }
971
972                         break;
973
974                 case BUS_MATCH_MESSAGE_TYPE:
975                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
976                                 matches_name_change = false;
977
978                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
979                         using_bloom = true;
980                         break;
981
982                 case BUS_MATCH_INTERFACE:
983                         if (!streq(c->value_str, "org.freedesktop.DBus"))
984                                 matches_name_change = false;
985
986                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
987                         using_bloom = true;
988                         break;
989
990                 case BUS_MATCH_MEMBER:
991                         if (!streq(c->value_str, "NameOwnerChanged"))
992                                 matches_name_change = false;
993
994                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
995                         using_bloom = true;
996                         break;
997
998                 case BUS_MATCH_PATH:
999                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1000                                 matches_name_change = false;
1001
1002                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1003                         using_bloom = true;
1004                         break;
1005
1006                 case BUS_MATCH_PATH_NAMESPACE:
1007                         if (!streq(c->value_str, "/")) {
1008                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1009                                 using_bloom = true;
1010                         }
1011                         break;
1012
1013                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1014                         char buf[sizeof("arg")-1 + 2 + 1];
1015
1016                         if (c->type - BUS_MATCH_ARG < 3)
1017                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1018
1019                         snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1020                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1021                         using_bloom = true;
1022                         break;
1023                 }
1024
1025                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1026                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1027
1028                         snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1029                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1030                         using_bloom = true;
1031                         break;
1032                 }
1033
1034                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1035                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1036
1037                         snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1038                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1039                         using_bloom = true;
1040                         break;
1041                 }
1042
1043                 case BUS_MATCH_DESTINATION:
1044                         /* The bloom filter does not include
1045                            the destination, since it is only
1046                            available for broadcast messages
1047                            which do not carry a destination
1048                            since they are undirected. */
1049                         break;
1050
1051                 case BUS_MATCH_ROOT:
1052                 case BUS_MATCH_VALUE:
1053                 case BUS_MATCH_LEAF:
1054                 case _BUS_MATCH_NODE_TYPE_MAX:
1055                 case _BUS_MATCH_NODE_TYPE_INVALID:
1056                         assert_not_reached("Invalid match type?");
1057                 }
1058         }
1059
1060         if (using_bloom)
1061                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1062
1063         m = alloca0(sz);
1064         m->size = sz;
1065         m->cookie = cookie;
1066         m->owner_id = id;
1067
1068         item = m->items;
1069
1070         if (src_id != KDBUS_MATCH_ID_ANY) {
1071                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1072                 item->type = KDBUS_ITEM_ID;
1073                 item->id = src_id;
1074                 item = KDBUS_ITEM_NEXT(item);
1075         }
1076
1077         if (using_bloom) {
1078                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1079                 item->type = KDBUS_ITEM_BLOOM_MASK;
1080                 memcpy(item->data64, bloom, bus->bloom_size);
1081                 item = KDBUS_ITEM_NEXT(item);
1082         }
1083
1084         if (sender) {
1085                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1086                 item->type = KDBUS_ITEM_NAME;
1087                 memcpy(item->str, sender, sender_length + 1);
1088         }
1089
1090         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1091         if (r < 0)
1092                 return -errno;
1093
1094         if (matches_name_change) {
1095
1096                 /* If this match could theoretically match
1097                  * NameOwnerChanged messages, we need to
1098                  * install a second non-bloom filter explitly
1099                  * for it */
1100
1101                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1102                 if (r < 0)
1103                         return r;
1104         }
1105
1106         return 0;
1107 }
1108
1109 #define internal_match(bus, m)                                          \
1110         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1111          ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1112          : (m))
1113
1114 static int bus_add_match_internal_dbus1(
1115                 sd_bus *bus,
1116                 const char *match) {
1117
1118         const char *e;
1119
1120         assert(bus);
1121         assert(match);
1122
1123         e = internal_match(bus, match);
1124
1125         return sd_bus_call_method(
1126                         bus,
1127                         "org.freedesktop.DBus",
1128                         "/org/freedesktop/DBus",
1129                         "org.freedesktop.DBus",
1130                         "AddMatch",
1131                         NULL,
1132                         NULL,
1133                         "s",
1134                         e);
1135 }
1136
1137 int bus_add_match_internal(
1138                 sd_bus *bus,
1139                 const char *match,
1140                 struct bus_match_component *components,
1141                 unsigned n_components,
1142                 uint64_t cookie) {
1143
1144         assert(bus);
1145         assert(match);
1146
1147         if (bus->is_kernel)
1148                 return bus_add_match_internal_kernel(bus, 0, components, n_components, cookie);
1149         else
1150                 return bus_add_match_internal_dbus1(bus, match);
1151 }
1152
1153 int bus_remove_match_internal_kernel(
1154                 sd_bus *bus,
1155                 uint64_t id,
1156                 uint64_t cookie) {
1157
1158         struct kdbus_cmd_match m;
1159         int r;
1160
1161         assert(bus);
1162
1163         zero(m);
1164         m.size = offsetof(struct kdbus_cmd_match, items);
1165         m.cookie = cookie;
1166         m.owner_id = id;
1167
1168         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1169         if (r < 0)
1170                 return -errno;
1171
1172         return 0;
1173 }
1174
1175 static int bus_remove_match_internal_dbus1(
1176                 sd_bus *bus,
1177                 const char *match) {
1178
1179         const char *e;
1180
1181         assert(bus);
1182         assert(match);
1183
1184         e = internal_match(bus, match);
1185
1186         return sd_bus_call_method(
1187                         bus,
1188                         "org.freedesktop.DBus",
1189                         "/org/freedesktop/DBus",
1190                         "org.freedesktop.DBus",
1191                         "RemoveMatch",
1192                         NULL,
1193                         NULL,
1194                         "s",
1195                         e);
1196 }
1197
1198 int bus_remove_match_internal(
1199                 sd_bus *bus,
1200                 const char *match,
1201                 uint64_t cookie) {
1202
1203         assert(bus);
1204         assert(match);
1205
1206         if (bus->is_kernel)
1207                 return bus_remove_match_internal_kernel(bus, 0, cookie);
1208         else
1209                 return bus_remove_match_internal_dbus1(bus, match);
1210 }
1211
1212 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1213         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1214         const char *mid;
1215         int r;
1216
1217         assert_return(bus, -EINVAL);
1218         assert_return(name, -EINVAL);
1219         assert_return(machine, -EINVAL);
1220         assert_return(!bus_pid_changed(bus), -ECHILD);
1221         assert_return(service_name_is_valid(name), -EINVAL);
1222
1223         if (!BUS_IS_OPEN(bus->state))
1224                 return -ENOTCONN;
1225
1226         if (streq_ptr(name, bus->unique_name))
1227                 return sd_id128_get_machine(machine);
1228
1229         r = sd_bus_message_new_method_call(
1230                         bus,
1231                         &m,
1232                         name,
1233                         "/",
1234                         "org.freedesktop.DBus.Peer",
1235                         "GetMachineId");
1236         if (r < 0)
1237                 return r;
1238
1239         r = sd_bus_message_set_auto_start(m, false);
1240         if (r < 0)
1241                 return r;
1242
1243         r = sd_bus_call(bus, m, 0, NULL, &reply);
1244         if (r < 0)
1245                 return r;
1246
1247         r = sd_bus_message_read(reply, "s", &mid);
1248         if (r < 0)
1249                 return r;
1250
1251         return sd_id128_from_string(mid, machine);
1252 }