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