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