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