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