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