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