chiark / gitweb /
sd-bus: sync kdbus.h (ABI break)
[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_OWNED_NAME)
282                                 entry_name = item->name.name;
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 - offsetof(struct kdbus_item, caps.caps);
499                                 c->capability = memdup(item->caps.caps, 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_OWNED_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_DESCRIPTION:
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                         return -ENOMEM;
831
832                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
833         }
834
835         if (bus->is_kernel) {
836                 struct kdbus_cmd_info cmd = {};
837                 struct kdbus_info *creator_info;
838
839                 cmd.size = sizeof(cmd);
840                 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
841                 if (r < 0)
842                         return -errno;
843
844                 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
845
846                 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
847                 kernel_cmd_free(bus, cmd.offset);
848
849                 if (r < 0)
850                         return r;
851         } else {
852                 r = bus_creds_add_more(c, mask, pid, 0);
853                 if (r < 0)
854                         return r;
855         }
856
857         *ret = c;
858         c = NULL;
859         return 0;
860 }
861
862 static int add_name_change_match(sd_bus *bus,
863                                  uint64_t cookie,
864                                  const char *name,
865                                  const char *old_owner,
866                                  const char *new_owner) {
867
868         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
869         int is_name_id = -1, r;
870         struct kdbus_item *item;
871
872         assert(bus);
873
874         /* If we encounter a match that could match against
875          * NameOwnerChanged messages, then we need to create
876          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
877          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
878          * multiple if the match is underspecified.
879          *
880          * The NameOwnerChanged signals take three parameters with
881          * unique or well-known names, but only some forms actually
882          * exist:
883          *
884          * WELLKNOWN, "", UNIQUE       â†’ KDBUS_ITEM_NAME_ADD
885          * WELLKNOWN, UNIQUE, ""       â†’ KDBUS_ITEM_NAME_REMOVE
886          * WELLKNOWN, UNIQUE, UNIQUE   â†’ KDBUS_ITEM_NAME_CHANGE
887          * UNIQUE, "", UNIQUE          â†’ KDBUS_ITEM_ID_ADD
888          * UNIQUE, UNIQUE, ""          â†’ KDBUS_ITEM_ID_REMOVE
889          *
890          * For the latter two the two unique names must be identical.
891          *
892          * */
893
894         if (name) {
895                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
896                 if (is_name_id < 0)
897                         return 0;
898         }
899
900         if (!isempty(old_owner)) {
901                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
902                 if (r < 0)
903                         return 0;
904                 if (r == 0)
905                         return 0;
906                 if (is_name_id > 0 && old_owner_id != name_id)
907                         return 0;
908         } else
909                 old_owner_id = KDBUS_MATCH_ID_ANY;
910
911         if (!isempty(new_owner)) {
912                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
913                 if (r < 0)
914                         return r;
915                 if (r == 0)
916                         return 0;
917                 if (is_name_id > 0 && new_owner_id != name_id)
918                         return 0;
919         } else
920                 new_owner_id = KDBUS_MATCH_ID_ANY;
921
922         if (is_name_id <= 0) {
923                 struct kdbus_cmd_match *m;
924                 size_t sz, l;
925
926                 /* If the name argument is missing or is a well-known
927                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
928                  * matches for it */
929
930                 l = name ? strlen(name) + 1 : 0;
931
932                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
933                             offsetof(struct kdbus_item, name_change) +
934                             offsetof(struct kdbus_notify_name_change, name) +
935                             l);
936
937                 m = alloca0_align(sz, 8);
938                 m->size = sz;
939                 m->cookie = cookie;
940
941                 item = m->items;
942                 item->size =
943                         offsetof(struct kdbus_item, name_change) +
944                         offsetof(struct kdbus_notify_name_change, name) +
945                         l;
946
947                 item->name_change.old_id.id = old_owner_id;
948                 item->name_change.new_id.id = new_owner_id;
949
950                 if (name)
951                         memcpy(item->name_change.name, name, l);
952
953                 /* If the old name is unset or empty, then
954                  * this can match against added names */
955                 if (!old_owner || old_owner[0] == 0) {
956                         item->type = KDBUS_ITEM_NAME_ADD;
957
958                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
959                         if (r < 0)
960                                 return -errno;
961                 }
962
963                 /* If the new name is unset or empty, then
964                  * this can match against removed names */
965                 if (!new_owner || new_owner[0] == 0) {
966                         item->type = KDBUS_ITEM_NAME_REMOVE;
967
968                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
969                         if (r < 0)
970                                 return -errno;
971                 }
972
973                 /* The CHANGE match we need in either case, because
974                  * what is reported as a name change by the kernel
975                  * might just be an owner change between starter and
976                  * normal clients. For userspace such a change should
977                  * be considered a removal/addition, hence let's
978                  * subscribe to this unconditionally. */
979                 item->type = KDBUS_ITEM_NAME_CHANGE;
980                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
981                 if (r < 0)
982                         return -errno;
983         }
984
985         if (is_name_id != 0) {
986                 struct kdbus_cmd_match *m;
987                 uint64_t sz;
988
989                 /* If the name argument is missing or is a unique
990                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
991                  * for it */
992
993                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
994                             offsetof(struct kdbus_item, id_change) +
995                             sizeof(struct kdbus_notify_id_change));
996
997                 m = alloca0_align(sz, 8);
998                 m->size = sz;
999                 m->cookie = cookie;
1000
1001                 item = m->items;
1002                 item->size =
1003                         offsetof(struct kdbus_item, id_change) +
1004                         sizeof(struct kdbus_notify_id_change);
1005                 item->id_change.id = name_id;
1006
1007                 /* If the old name is unset or empty, then this can
1008                  * match against added ids */
1009                 if (!old_owner || old_owner[0] == 0) {
1010                         item->type = KDBUS_ITEM_ID_ADD;
1011
1012                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1013                         if (r < 0)
1014                                 return -errno;
1015                 }
1016
1017                 /* If thew new name is unset or empty, then this can
1018                  * match against removed ids */
1019                 if (!new_owner || new_owner[0] == 0) {
1020                         item->type = KDBUS_ITEM_ID_REMOVE;
1021
1022                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1023                         if (r < 0)
1024                                 return -errno;
1025                 }
1026         }
1027
1028         return 0;
1029 }
1030
1031 int bus_add_match_internal_kernel(
1032                 sd_bus *bus,
1033                 struct bus_match_component *components,
1034                 unsigned n_components,
1035                 uint64_t cookie) {
1036
1037         struct kdbus_cmd_match *m;
1038         struct kdbus_item *item;
1039         uint64_t *bloom;
1040         size_t sz;
1041         const char *sender = NULL;
1042         size_t sender_length = 0;
1043         uint64_t src_id = KDBUS_MATCH_ID_ANY;
1044         bool using_bloom = false;
1045         unsigned i;
1046         bool matches_name_change = true;
1047         const char *name_change_arg[3] = {};
1048         int r;
1049
1050         assert(bus);
1051
1052         bloom = alloca0(bus->bloom_size);
1053
1054         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1055
1056         for (i = 0; i < n_components; i++) {
1057                 struct bus_match_component *c = &components[i];
1058
1059                 switch (c->type) {
1060
1061                 case BUS_MATCH_SENDER:
1062                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1063                                 matches_name_change = false;
1064
1065                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1066                         if (r < 0)
1067                                 return r;
1068                         else if (r > 0)
1069                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1070                         else  {
1071                                 sender = c->value_str;
1072                                 sender_length = strlen(sender);
1073                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1074                         }
1075
1076                         break;
1077
1078                 case BUS_MATCH_MESSAGE_TYPE:
1079                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1080                                 matches_name_change = false;
1081
1082                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1083                         using_bloom = true;
1084                         break;
1085
1086                 case BUS_MATCH_INTERFACE:
1087                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1088                                 matches_name_change = false;
1089
1090                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1091                         using_bloom = true;
1092                         break;
1093
1094                 case BUS_MATCH_MEMBER:
1095                         if (!streq(c->value_str, "NameOwnerChanged"))
1096                                 matches_name_change = false;
1097
1098                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1099                         using_bloom = true;
1100                         break;
1101
1102                 case BUS_MATCH_PATH:
1103                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1104                                 matches_name_change = false;
1105
1106                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1107                         using_bloom = true;
1108                         break;
1109
1110                 case BUS_MATCH_PATH_NAMESPACE:
1111                         if (!streq(c->value_str, "/")) {
1112                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1113                                 using_bloom = true;
1114                         }
1115                         break;
1116
1117                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1118                         char buf[sizeof("arg")-1 + 2 + 1];
1119
1120                         if (c->type - BUS_MATCH_ARG < 3)
1121                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1122
1123                         snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1124                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1125                         using_bloom = true;
1126                         break;
1127                 }
1128
1129                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1130                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1131
1132                         snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1133                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1134                         using_bloom = true;
1135                         break;
1136                 }
1137
1138                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1139                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1140
1141                         snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1142                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1143                         using_bloom = true;
1144                         break;
1145                 }
1146
1147                 case BUS_MATCH_DESTINATION:
1148                         /* The bloom filter does not include
1149                            the destination, since it is only
1150                            available for broadcast messages
1151                            which do not carry a destination
1152                            since they are undirected. */
1153                         break;
1154
1155                 case BUS_MATCH_ROOT:
1156                 case BUS_MATCH_VALUE:
1157                 case BUS_MATCH_LEAF:
1158                 case _BUS_MATCH_NODE_TYPE_MAX:
1159                 case _BUS_MATCH_NODE_TYPE_INVALID:
1160                         assert_not_reached("Invalid match type?");
1161                 }
1162         }
1163
1164         if (using_bloom)
1165                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1166
1167         m = alloca0_align(sz, 8);
1168         m->size = sz;
1169         m->cookie = cookie;
1170
1171         item = m->items;
1172
1173         if (src_id != KDBUS_MATCH_ID_ANY) {
1174                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1175                 item->type = KDBUS_ITEM_ID;
1176                 item->id = src_id;
1177                 item = KDBUS_ITEM_NEXT(item);
1178         }
1179
1180         if (using_bloom) {
1181                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1182                 item->type = KDBUS_ITEM_BLOOM_MASK;
1183                 memcpy(item->data64, bloom, bus->bloom_size);
1184                 item = KDBUS_ITEM_NEXT(item);
1185         }
1186
1187         if (sender) {
1188                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1189                 item->type = KDBUS_ITEM_NAME;
1190                 memcpy(item->str, sender, sender_length + 1);
1191         }
1192
1193         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1194         if (r < 0)
1195                 return -errno;
1196
1197         if (matches_name_change) {
1198
1199                 /* If this match could theoretically match
1200                  * NameOwnerChanged messages, we need to
1201                  * install a second non-bloom filter explitly
1202                  * for it */
1203
1204                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1205                 if (r < 0)
1206                         return r;
1207         }
1208
1209         return 0;
1210 }
1211
1212 #define internal_match(bus, m)                                          \
1213         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1214          ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1215          : (m))
1216
1217 static int bus_add_match_internal_dbus1(
1218                 sd_bus *bus,
1219                 const char *match) {
1220
1221         const char *e;
1222
1223         assert(bus);
1224         assert(match);
1225
1226         e = internal_match(bus, match);
1227
1228         return sd_bus_call_method(
1229                         bus,
1230                         "org.freedesktop.DBus",
1231                         "/org/freedesktop/DBus",
1232                         "org.freedesktop.DBus",
1233                         "AddMatch",
1234                         NULL,
1235                         NULL,
1236                         "s",
1237                         e);
1238 }
1239
1240 int bus_add_match_internal(
1241                 sd_bus *bus,
1242                 const char *match,
1243                 struct bus_match_component *components,
1244                 unsigned n_components,
1245                 uint64_t cookie) {
1246
1247         assert(bus);
1248
1249         if (bus->is_kernel)
1250                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1251         else
1252                 return bus_add_match_internal_dbus1(bus, match);
1253 }
1254
1255 int bus_remove_match_internal_kernel(
1256                 sd_bus *bus,
1257                 uint64_t cookie) {
1258
1259         struct kdbus_cmd_match m;
1260         int r;
1261
1262         assert(bus);
1263
1264         zero(m);
1265         m.size = offsetof(struct kdbus_cmd_match, items);
1266         m.cookie = cookie;
1267
1268         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1269         if (r < 0)
1270                 return -errno;
1271
1272         return 0;
1273 }
1274
1275 static int bus_remove_match_internal_dbus1(
1276                 sd_bus *bus,
1277                 const char *match) {
1278
1279         const char *e;
1280
1281         assert(bus);
1282         assert(match);
1283
1284         e = internal_match(bus, match);
1285
1286         return sd_bus_call_method(
1287                         bus,
1288                         "org.freedesktop.DBus",
1289                         "/org/freedesktop/DBus",
1290                         "org.freedesktop.DBus",
1291                         "RemoveMatch",
1292                         NULL,
1293                         NULL,
1294                         "s",
1295                         e);
1296 }
1297
1298 int bus_remove_match_internal(
1299                 sd_bus *bus,
1300                 const char *match,
1301                 uint64_t cookie) {
1302
1303         assert(bus);
1304
1305         if (bus->is_kernel)
1306                 return bus_remove_match_internal_kernel(bus, cookie);
1307         else
1308                 return bus_remove_match_internal_dbus1(bus, match);
1309 }
1310
1311 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1312         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1313         const char *mid;
1314         int r;
1315
1316         assert_return(bus, -EINVAL);
1317         assert_return(name, -EINVAL);
1318         assert_return(machine, -EINVAL);
1319         assert_return(!bus_pid_changed(bus), -ECHILD);
1320         assert_return(service_name_is_valid(name), -EINVAL);
1321
1322         if (!BUS_IS_OPEN(bus->state))
1323                 return -ENOTCONN;
1324
1325         if (streq_ptr(name, bus->unique_name))
1326                 return sd_id128_get_machine(machine);
1327
1328         r = sd_bus_message_new_method_call(
1329                         bus,
1330                         &m,
1331                         name,
1332                         "/",
1333                         "org.freedesktop.DBus.Peer",
1334                         "GetMachineId");
1335         if (r < 0)
1336                 return r;
1337
1338         r = sd_bus_message_set_auto_start(m, false);
1339         if (r < 0)
1340                 return r;
1341
1342         r = sd_bus_call(bus, m, 0, NULL, &reply);
1343         if (r < 0)
1344                 return r;
1345
1346         r = sd_bus_message_read(reply, "s", &mid);
1347         if (r < 0)
1348                 return r;
1349
1350         return sd_id128_from_string(mid, machine);
1351 }