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