chiark / gitweb /
util: avoid non-portable __WORDSIZE
[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_align(size, 8);
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_align(offsetof(struct kdbus_cmd_name, name) + l + 1, 8);
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_align(size, 8);
380                 cmd->id = id;
381         } else {
382                 size = offsetof(struct kdbus_cmd_conn_info, name) + strlen(name) + 1;
383                 cmd = alloca0_align(size, 8);
384                 strcpy(cmd->name, name);
385         }
386
387         cmd->size = size;
388         kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
389
390         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
391         if (r < 0)
392                 return -errno;
393
394         conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
395
396         /* Non-activated names are considered not available */
397         if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
398                 return name[0] == ':' ? -ENXIO : -ESRCH;
399
400         c = bus_creds_new();
401         if (!c)
402                 return -ENOMEM;
403
404         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
405                 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
406                         return -ENOMEM;
407
408                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
409         }
410
411         KDBUS_ITEM_FOREACH(item, conn_info, items) {
412
413                 switch (item->type) {
414
415                 case KDBUS_ITEM_CREDS:
416                         m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
417
418                         if (m) {
419                                 c->uid = (uid_t) item->creds.uid;
420                                 c->pid = (pid_t) item->creds.pid;
421                                 c->gid = (gid_t) item->creds.gid;
422                                 c->mask |= m;
423                         }
424
425                         if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
426                                 c->tid = (pid_t) item->creds.tid;
427                                 c->mask |= SD_BUS_CREDS_TID;
428                         }
429
430                         if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
431                                 c->pid_starttime = item->creds.starttime;
432                                 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
433                         }
434
435                         break;
436
437                 case KDBUS_ITEM_PID_COMM:
438                         if (mask & SD_BUS_CREDS_COMM) {
439                                 c->comm = strdup(item->str);
440                                 if (!c->comm) {
441                                         r = -ENOMEM;
442                                         goto fail;
443                                 }
444
445                                 c->mask |= SD_BUS_CREDS_COMM;
446                         }
447                         break;
448
449                 case KDBUS_ITEM_TID_COMM:
450                         if (mask & SD_BUS_CREDS_TID_COMM) {
451                                 c->tid_comm = strdup(item->str);
452                                 if (!c->tid_comm) {
453                                         r = -ENOMEM;
454                                         goto fail;
455                                 }
456
457                                 c->mask |= SD_BUS_CREDS_TID_COMM;
458                         }
459                         break;
460
461                 case KDBUS_ITEM_EXE:
462                         if (mask & SD_BUS_CREDS_EXE) {
463                                 c->exe = strdup(item->str);
464                                 if (!c->exe) {
465                                         r = -ENOMEM;
466                                         goto fail;
467                                 }
468
469                                 c->mask |= SD_BUS_CREDS_EXE;
470                         }
471                         break;
472
473                 case KDBUS_ITEM_CMDLINE:
474                         if (mask & SD_BUS_CREDS_CMDLINE) {
475                                 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
476                                 c->cmdline = memdup(item->data, c->cmdline_size);
477                                 if (!c->cmdline) {
478                                         r = -ENOMEM;
479                                         goto fail;
480                                 }
481
482                                 c->mask |= SD_BUS_CREDS_CMDLINE;
483                         }
484                         break;
485
486                 case KDBUS_ITEM_CGROUP:
487                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
488                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
489                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
490
491                         if (m) {
492                                 c->cgroup = strdup(item->str);
493                                 if (!c->cgroup) {
494                                         r = -ENOMEM;
495                                         goto fail;
496                                 }
497
498                                 r = bus_get_root_path(bus);
499                                 if (r < 0)
500                                         goto fail;
501
502                                 c->cgroup_root = strdup(bus->cgroup_root);
503                                 if (!c->cgroup_root) {
504                                         r = -ENOMEM;
505                                         goto fail;
506                                 }
507
508                                 c->mask |= m;
509                         }
510                         break;
511
512                 case KDBUS_ITEM_CAPS:
513                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
514                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
515
516                         if (m) {
517                                 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
518                                 c->capability = memdup(item->data, c->capability_size);
519                                 if (!c->capability) {
520                                         r = -ENOMEM;
521                                         goto fail;
522                                 }
523
524                                 c->mask |= m;
525                         }
526                         break;
527
528                 case KDBUS_ITEM_SECLABEL:
529                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
530                                 c->label = strdup(item->str);
531                                 if (!c->label) {
532                                         r = -ENOMEM;
533                                         goto fail;
534                                 }
535
536                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
537                         }
538                         break;
539
540                 case KDBUS_ITEM_AUDIT:
541                         m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
542
543                         if (m) {
544                                 c->audit_session_id = item->audit.sessionid;
545                                 c->audit_login_uid = item->audit.loginuid;
546                                 c->mask |= m;
547                         }
548                         break;
549
550                 case KDBUS_ITEM_NAME:
551                         if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
552                                 r = strv_extend(&c->well_known_names, item->name.name);
553                                 if (r < 0)
554                                         goto fail;
555
556                                 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
557                         }
558                         break;
559
560                 case KDBUS_ITEM_CONN_NAME:
561                         if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
562                                 c->conn_name = strdup(item->str);
563                                 if (!c->conn_name) {
564                                         r = -ENOMEM;
565                                         goto fail;
566                                 }
567
568                                 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
569                         }
570                         break;
571                 }
572         }
573
574         if (creds) {
575                 *creds = c;
576                 c = NULL;
577         }
578
579         r = 0;
580
581 fail:
582         ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
583         return r;
584 }
585
586 static int bus_get_owner_dbus1(
587                 sd_bus *bus,
588                 const char *name,
589                 uint64_t mask,
590                 sd_bus_creds **creds) {
591
592         _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
593         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
594         const char *unique = NULL;
595         pid_t pid = 0;
596         int r;
597
598         /* Only query the owner if the caller wants to know it or if
599          * the caller just wants to check whether a name exists */
600         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
601                 r = sd_bus_call_method(
602                                 bus,
603                                 "org.freedesktop.DBus",
604                                 "/org/freedesktop/DBus",
605                                 "org.freedesktop.DBus",
606                                 "GetNameOwner",
607                                 NULL,
608                                 &reply_unique,
609                                 "s",
610                                 name);
611                 if (r < 0)
612                         return r;
613
614                 r = sd_bus_message_read(reply_unique, "s", &unique);
615                 if (r < 0)
616                         return r;
617         }
618
619         if (mask != 0) {
620                 c = bus_creds_new();
621                 if (!c)
622                         return -ENOMEM;
623
624                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
625                         c->unique_name = strdup(unique);
626                         if (!c->unique_name)
627                                 return -ENOMEM;
628
629                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
630                 }
631
632                 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
633                             SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
634                             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|
635                             SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
636                             SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
637                         uint32_t u;
638
639                         r = sd_bus_call_method(
640                                         bus,
641                                         "org.freedesktop.DBus",
642                                         "/org/freedesktop/DBus",
643                                         "org.freedesktop.DBus",
644                                         "GetConnectionUnixProcessID",
645                                         NULL,
646                                         &reply,
647                                         "s",
648                                         unique ? unique : name);
649                         if (r < 0)
650                                 return r;
651
652                         r = sd_bus_message_read(reply, "u", &u);
653                         if (r < 0)
654                                 return r;
655
656                         pid = u;
657                         if (mask & SD_BUS_CREDS_PID) {
658                                 c->pid = u;
659                                 c->mask |= SD_BUS_CREDS_PID;
660                         }
661
662                         reply = sd_bus_message_unref(reply);
663                 }
664
665                 if (mask & SD_BUS_CREDS_UID) {
666                         uint32_t u;
667
668                         r = sd_bus_call_method(
669                                         bus,
670                                         "org.freedesktop.DBus",
671                                         "/org/freedesktop/DBus",
672                                         "org.freedesktop.DBus",
673                                         "GetConnectionUnixUser",
674                                         NULL,
675                                         &reply,
676                                         "s",
677                                         unique ? unique : name);
678                         if (r < 0)
679                                 return r;
680
681                         r = sd_bus_message_read(reply, "u", &u);
682                         if (r < 0)
683                                 return r;
684
685                         c->uid = u;
686                         c->mask |= SD_BUS_CREDS_UID;
687
688                         reply = sd_bus_message_unref(reply);
689                 }
690
691                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
692                         const void *p = NULL;
693                         size_t sz = 0;
694
695                         r = sd_bus_call_method(
696                                         bus,
697                                         "org.freedesktop.DBus",
698                                         "/org/freedesktop/DBus",
699                                         "org.freedesktop.DBus",
700                                         "GetConnectionSELinuxSecurityContext",
701                                         NULL,
702                                         &reply,
703                                         "s",
704                                         unique ? unique : name);
705                         if (r < 0)
706                                 return r;
707
708                         r = sd_bus_message_read_array(reply, 'y', &p, &sz);
709                         if (r < 0)
710                                 return r;
711
712                         c->label = strndup(p, sz);
713                         if (!c->label)
714                                 return -ENOMEM;
715
716                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
717                 }
718
719                 r = bus_creds_add_more(c, mask, pid, 0);
720                 if (r < 0)
721                         return r;
722         }
723
724         if (creds) {
725                 *creds = c;
726                 c = NULL;
727         }
728
729         return 0;
730 }
731
732 _public_ int sd_bus_get_owner(
733                 sd_bus *bus,
734                 const char *name,
735                 uint64_t mask,
736                 sd_bus_creds **creds) {
737
738         assert_return(bus, -EINVAL);
739         assert_return(name, -EINVAL);
740         assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
741         assert_return(mask == 0 || creds, -EINVAL);
742         assert_return(!bus_pid_changed(bus), -ECHILD);
743         assert_return(service_name_is_valid(name), -EINVAL);
744         assert_return(bus->bus_client, -ENODATA);
745
746         if (!BUS_IS_OPEN(bus->state))
747                 return -ENOTCONN;
748
749         if (bus->is_kernel)
750                 return bus_get_owner_kdbus(bus, name, mask, creds);
751         else
752                 return bus_get_owner_dbus1(bus, name, mask, creds);
753 }
754
755 static int add_name_change_match(sd_bus *bus,
756                                  uint64_t cookie,
757                                  const char *name,
758                                  const char *old_owner,
759                                  const char *new_owner) {
760
761         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
762         int is_name_id = -1, r;
763         struct kdbus_item *item;
764
765         assert(bus);
766
767         /* If we encounter a match that could match against
768          * NameOwnerChanged messages, then we need to create
769          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
770          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
771          * multiple if the match is underspecified.
772          *
773          * The NameOwnerChanged signals take three parameters with
774          * unique or well-known names, but only some forms actually
775          * exist:
776          *
777          * WELLKNOWN, "", UNIQUE       → KDBUS_ITEM_NAME_ADD
778          * WELLKNOWN, UNIQUE, ""       → KDBUS_ITEM_NAME_REMOVE
779          * WELLKNOWN, UNIQUE, UNIQUE   → KDBUS_ITEM_NAME_CHANGE
780          * UNIQUE, "", UNIQUE          → KDBUS_ITEM_ID_ADD
781          * UNIQUE, UNIQUE, ""          → KDBUS_ITEM_ID_REMOVE
782          *
783          * For the latter two the two unique names must be identical.
784          *
785          * */
786
787         if (name) {
788                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
789                 if (is_name_id < 0)
790                         return 0;
791         }
792
793         if (!isempty(old_owner)) {
794                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
795                 if (r < 0)
796                         return 0;
797                 if (r == 0)
798                         return 0;
799                 if (is_name_id > 0 && old_owner_id != name_id)
800                         return 0;
801         } else
802                 old_owner_id = KDBUS_MATCH_ID_ANY;
803
804         if (!isempty(new_owner)) {
805                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
806                 if (r < 0)
807                         return r;
808                 if (r == 0)
809                         return 0;
810                 if (is_name_id > 0 && new_owner_id != name_id)
811                         return 0;
812         } else
813                 new_owner_id = KDBUS_MATCH_ID_ANY;
814
815         if (is_name_id <= 0) {
816                 struct kdbus_cmd_match *m;
817                 size_t sz, l;
818
819                 /* If the name argument is missing or is a well-known
820                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
821                  * matches for it */
822
823                 l = name ? strlen(name) + 1 : 0;
824
825                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
826                             offsetof(struct kdbus_item, name_change) +
827                             offsetof(struct kdbus_notify_name_change, name) +
828                             l);
829
830                 m = alloca0_align(sz, 8);
831                 m->size = sz;
832                 m->cookie = cookie;
833
834                 item = m->items;
835                 item->size =
836                         offsetof(struct kdbus_item, name_change) +
837                         offsetof(struct kdbus_notify_name_change, name) +
838                         l;
839
840                 item->name_change.old.id = old_owner_id;
841                 item->name_change.new.id = new_owner_id;
842
843                 if (name)
844                         memcpy(item->name_change.name, name, l);
845
846                 /* If the old name is unset or empty, then
847                  * this can match against added names */
848                 if (!old_owner || old_owner[0] == 0) {
849                         item->type = KDBUS_ITEM_NAME_ADD;
850
851                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
852                         if (r < 0)
853                                 return -errno;
854                 }
855
856                 /* If the new name is unset or empty, then
857                  * this can match against removed names */
858                 if (!new_owner || new_owner[0] == 0) {
859                         item->type = KDBUS_ITEM_NAME_REMOVE;
860
861                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
862                         if (r < 0)
863                                 return -errno;
864                 }
865
866                 /* The CHANGE match we need in either case, because
867                  * what is reported as a name change by the kernel
868                  * might just be an owner change between starter and
869                  * normal clients. For userspace such a change should
870                  * be considered a removal/addition, hence let's
871                  * subscribe to this unconditionally. */
872                 item->type = KDBUS_ITEM_NAME_CHANGE;
873                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
874                 if (r < 0)
875                         return -errno;
876         }
877
878         if (is_name_id != 0) {
879                 struct kdbus_cmd_match *m;
880                 uint64_t sz;
881
882                 /* If the name argument is missing or is a unique
883                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
884                  * for it */
885
886                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
887                             offsetof(struct kdbus_item, id_change) +
888                             sizeof(struct kdbus_notify_id_change));
889
890                 m = alloca0_align(sz, 8);
891                 m->size = sz;
892                 m->cookie = cookie;
893
894                 item = m->items;
895                 item->size =
896                         offsetof(struct kdbus_item, id_change) +
897                         sizeof(struct kdbus_notify_id_change);
898                 item->id_change.id = name_id;
899
900                 /* If the old name is unset or empty, then this can
901                  * match against added ids */
902                 if (!old_owner || old_owner[0] == 0) {
903                         item->type = KDBUS_ITEM_ID_ADD;
904
905                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
906                         if (r < 0)
907                                 return -errno;
908                 }
909
910                 /* If thew new name is unset or empty, then this can
911                  * match against removed ids */
912                 if (!new_owner || new_owner[0] == 0) {
913                         item->type = KDBUS_ITEM_ID_REMOVE;
914
915                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
916                         if (r < 0)
917                                 return -errno;
918                 }
919         }
920
921         return 0;
922 }
923
924 int bus_add_match_internal_kernel(
925                 sd_bus *bus,
926                 struct bus_match_component *components,
927                 unsigned n_components,
928                 uint64_t cookie) {
929
930         struct kdbus_cmd_match *m;
931         struct kdbus_item *item;
932         uint64_t *bloom;
933         size_t sz;
934         const char *sender = NULL;
935         size_t sender_length = 0;
936         uint64_t src_id = KDBUS_MATCH_ID_ANY;
937         bool using_bloom = false;
938         unsigned i;
939         bool matches_name_change = true;
940         const char *name_change_arg[3] = {};
941         int r;
942
943         assert(bus);
944
945         bloom = alloca0(bus->bloom_size);
946
947         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
948
949         for (i = 0; i < n_components; i++) {
950                 struct bus_match_component *c = &components[i];
951
952                 switch (c->type) {
953
954                 case BUS_MATCH_SENDER:
955                         if (!streq(c->value_str, "org.freedesktop.DBus"))
956                                 matches_name_change = false;
957
958                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
959                         if (r < 0)
960                                 return r;
961                         else if (r > 0)
962                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
963                         else  {
964                                 sender = c->value_str;
965                                 sender_length = strlen(sender);
966                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
967                         }
968
969                         break;
970
971                 case BUS_MATCH_MESSAGE_TYPE:
972                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
973                                 matches_name_change = false;
974
975                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
976                         using_bloom = true;
977                         break;
978
979                 case BUS_MATCH_INTERFACE:
980                         if (!streq(c->value_str, "org.freedesktop.DBus"))
981                                 matches_name_change = false;
982
983                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
984                         using_bloom = true;
985                         break;
986
987                 case BUS_MATCH_MEMBER:
988                         if (!streq(c->value_str, "NameOwnerChanged"))
989                                 matches_name_change = false;
990
991                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
992                         using_bloom = true;
993                         break;
994
995                 case BUS_MATCH_PATH:
996                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
997                                 matches_name_change = false;
998
999                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1000                         using_bloom = true;
1001                         break;
1002
1003                 case BUS_MATCH_PATH_NAMESPACE:
1004                         if (!streq(c->value_str, "/")) {
1005                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1006                                 using_bloom = true;
1007                         }
1008                         break;
1009
1010                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1011                         char buf[sizeof("arg")-1 + 2 + 1];
1012
1013                         if (c->type - BUS_MATCH_ARG < 3)
1014                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1015
1016                         snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1017                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1018                         using_bloom = true;
1019                         break;
1020                 }
1021
1022                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1023                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1024
1025                         snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1026                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1027                         using_bloom = true;
1028                         break;
1029                 }
1030
1031                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1032                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1033
1034                         snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1035                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1036                         using_bloom = true;
1037                         break;
1038                 }
1039
1040                 case BUS_MATCH_DESTINATION:
1041                         /* The bloom filter does not include
1042                            the destination, since it is only
1043                            available for broadcast messages
1044                            which do not carry a destination
1045                            since they are undirected. */
1046                         break;
1047
1048                 case BUS_MATCH_ROOT:
1049                 case BUS_MATCH_VALUE:
1050                 case BUS_MATCH_LEAF:
1051                 case _BUS_MATCH_NODE_TYPE_MAX:
1052                 case _BUS_MATCH_NODE_TYPE_INVALID:
1053                         assert_not_reached("Invalid match type?");
1054                 }
1055         }
1056
1057         if (using_bloom)
1058                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1059
1060         m = alloca0_align(sz, 8);
1061         m->size = sz;
1062         m->cookie = cookie;
1063
1064         item = m->items;
1065
1066         if (src_id != KDBUS_MATCH_ID_ANY) {
1067                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1068                 item->type = KDBUS_ITEM_ID;
1069                 item->id = src_id;
1070                 item = KDBUS_ITEM_NEXT(item);
1071         }
1072
1073         if (using_bloom) {
1074                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1075                 item->type = KDBUS_ITEM_BLOOM_MASK;
1076                 memcpy(item->data64, bloom, bus->bloom_size);
1077                 item = KDBUS_ITEM_NEXT(item);
1078         }
1079
1080         if (sender) {
1081                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1082                 item->type = KDBUS_ITEM_NAME;
1083                 memcpy(item->str, sender, sender_length + 1);
1084         }
1085
1086         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1087         if (r < 0)
1088                 return -errno;
1089
1090         if (matches_name_change) {
1091
1092                 /* If this match could theoretically match
1093                  * NameOwnerChanged messages, we need to
1094                  * install a second non-bloom filter explitly
1095                  * for it */
1096
1097                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1098                 if (r < 0)
1099                         return r;
1100         }
1101
1102         return 0;
1103 }
1104
1105 #define internal_match(bus, m)                                          \
1106         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1107          ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1108          : (m))
1109
1110 static int bus_add_match_internal_dbus1(
1111                 sd_bus *bus,
1112                 const char *match) {
1113
1114         const char *e;
1115
1116         assert(bus);
1117         assert(match);
1118
1119         e = internal_match(bus, match);
1120
1121         return sd_bus_call_method(
1122                         bus,
1123                         "org.freedesktop.DBus",
1124                         "/org/freedesktop/DBus",
1125                         "org.freedesktop.DBus",
1126                         "AddMatch",
1127                         NULL,
1128                         NULL,
1129                         "s",
1130                         e);
1131 }
1132
1133 int bus_add_match_internal(
1134                 sd_bus *bus,
1135                 const char *match,
1136                 struct bus_match_component *components,
1137                 unsigned n_components,
1138                 uint64_t cookie) {
1139
1140         assert(bus);
1141
1142         if (bus->is_kernel)
1143                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1144         else
1145                 return bus_add_match_internal_dbus1(bus, match);
1146 }
1147
1148 int bus_remove_match_internal_kernel(
1149                 sd_bus *bus,
1150                 uint64_t cookie) {
1151
1152         struct kdbus_cmd_match m;
1153         int r;
1154
1155         assert(bus);
1156
1157         zero(m);
1158         m.size = offsetof(struct kdbus_cmd_match, items);
1159         m.cookie = cookie;
1160
1161         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1162         if (r < 0)
1163                 return -errno;
1164
1165         return 0;
1166 }
1167
1168 static int bus_remove_match_internal_dbus1(
1169                 sd_bus *bus,
1170                 const char *match) {
1171
1172         const char *e;
1173
1174         assert(bus);
1175         assert(match);
1176
1177         e = internal_match(bus, match);
1178
1179         return sd_bus_call_method(
1180                         bus,
1181                         "org.freedesktop.DBus",
1182                         "/org/freedesktop/DBus",
1183                         "org.freedesktop.DBus",
1184                         "RemoveMatch",
1185                         NULL,
1186                         NULL,
1187                         "s",
1188                         e);
1189 }
1190
1191 int bus_remove_match_internal(
1192                 sd_bus *bus,
1193                 const char *match,
1194                 uint64_t cookie) {
1195
1196         assert(bus);
1197
1198         if (bus->is_kernel)
1199                 return bus_remove_match_internal_kernel(bus, cookie);
1200         else
1201                 return bus_remove_match_internal_dbus1(bus, match);
1202 }
1203
1204 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1205         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1206         const char *mid;
1207         int r;
1208
1209         assert_return(bus, -EINVAL);
1210         assert_return(name, -EINVAL);
1211         assert_return(machine, -EINVAL);
1212         assert_return(!bus_pid_changed(bus), -ECHILD);
1213         assert_return(service_name_is_valid(name), -EINVAL);
1214
1215         if (!BUS_IS_OPEN(bus->state))
1216                 return -ENOTCONN;
1217
1218         if (streq_ptr(name, bus->unique_name))
1219                 return sd_id128_get_machine(machine);
1220
1221         r = sd_bus_message_new_method_call(
1222                         bus,
1223                         &m,
1224                         name,
1225                         "/",
1226                         "org.freedesktop.DBus.Peer",
1227                         "GetMachineId");
1228         if (r < 0)
1229                 return r;
1230
1231         r = sd_bus_message_set_auto_start(m, false);
1232         if (r < 0)
1233                 return r;
1234
1235         r = sd_bus_call(bus, m, 0, NULL, &reply);
1236         if (r < 0)
1237                 return r;
1238
1239         r = sd_bus_message_read(reply, "s", &mid);
1240         if (r < 0)
1241                 return r;
1242
1243         return sd_id128_from_string(mid, machine);
1244 }