Line data Source code
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 <fcntl.h>
27 : #include <malloc.h>
28 : #include <sys/mman.h>
29 : #include <sys/prctl.h>
30 :
31 : /* When we include libgen.h because we need dirname() we immediately
32 : * undefine basename() since libgen.h defines it as a macro to the POSIX
33 : * version which is really broken. We prefer GNU basename(). */
34 : #include <libgen.h>
35 : #undef basename
36 :
37 : #include "util.h"
38 : #include "strv.h"
39 : #include "memfd-util.h"
40 : #include "capability.h"
41 : #include "fileio.h"
42 : #include "formats-util.h"
43 :
44 : #include "bus-internal.h"
45 : #include "bus-message.h"
46 : #include "bus-kernel.h"
47 : #include "bus-bloom.h"
48 : #include "bus-util.h"
49 : #include "bus-label.h"
50 :
51 : #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
52 :
53 15502 : int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
54 : int r;
55 :
56 15502 : assert(s);
57 15502 : assert(id);
58 :
59 15502 : if (!startswith(s, ":1."))
60 14 : return 0;
61 :
62 15488 : r = safe_atou64(s + 3, id);
63 15488 : if (r < 0)
64 0 : return r;
65 :
66 15488 : return 1;
67 : }
68 :
69 31066 : static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
70 31066 : assert(d);
71 31066 : assert(sz > 0);
72 :
73 31066 : *d = ALIGN8_PTR(*d);
74 :
75 : /* Note that p can be NULL, which encodes a region full of
76 : * zeroes, which is useful to optimize certain padding
77 : * conditions */
78 :
79 31066 : (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
80 31066 : (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
81 31066 : (*d)->vec.address = PTR_TO_UINT64(p);
82 31066 : (*d)->vec.size = sz;
83 :
84 31066 : *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
85 31066 : }
86 :
87 3 : static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t start, size_t sz) {
88 3 : assert(d);
89 3 : assert(memfd >= 0);
90 3 : assert(sz > 0);
91 :
92 3 : *d = ALIGN8_PTR(*d);
93 3 : (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
94 3 : (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
95 3 : (*d)->memfd.fd = memfd;
96 3 : (*d)->memfd.start = start;
97 3 : (*d)->memfd.size = sz;
98 :
99 3 : *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
100 3 : }
101 :
102 10 : static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
103 10 : assert(d);
104 10 : assert(s);
105 :
106 10 : *d = ALIGN8_PTR(*d);
107 :
108 10 : (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
109 10 : (*d)->type = KDBUS_ITEM_DST_NAME;
110 10 : memcpy((*d)->str, s, length + 1);
111 :
112 10 : *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
113 10 : }
114 :
115 33 : static struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) {
116 : struct kdbus_item *i;
117 :
118 33 : assert(d);
119 :
120 33 : i = ALIGN8_PTR(*d);
121 :
122 33 : i->size = offsetof(struct kdbus_item, bloom_filter) +
123 33 : offsetof(struct kdbus_bloom_filter, data) +
124 : length;
125 33 : i->type = KDBUS_ITEM_BLOOM_FILTER;
126 :
127 33 : *d = (struct kdbus_item *) ((uint8_t*) i + i->size);
128 :
129 33 : return &i->bloom_filter;
130 : }
131 :
132 2 : static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
133 2 : assert(d);
134 2 : assert(fds);
135 2 : assert(n_fds > 0);
136 :
137 2 : *d = ALIGN8_PTR(*d);
138 2 : (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
139 2 : (*d)->type = KDBUS_ITEM_FDS;
140 2 : memcpy((*d)->fds, fds, sizeof(int) * n_fds);
141 :
142 2 : *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
143 2 : }
144 :
145 32 : static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
146 : char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
147 : char *e;
148 :
149 32 : assert(data);
150 32 : assert(size > 0);
151 32 : assert(i < 64);
152 32 : assert(t);
153 :
154 32 : e = stpcpy(buf, "arg");
155 32 : if (i < 10)
156 32 : *(e++) = '0' + (char) i;
157 : else {
158 0 : *(e++) = '0' + (char) (i / 10);
159 0 : *(e++) = '0' + (char) (i % 10);
160 : }
161 :
162 32 : *e = 0;
163 32 : bloom_add_pair(data, size, n_hash, buf, t);
164 :
165 32 : strcpy(e, "-dot-prefix");
166 32 : bloom_add_prefixes(data, size, n_hash, buf, t, '.');
167 32 : strcpy(e, "-slash-prefix");
168 32 : bloom_add_prefixes(data, size, n_hash, buf, t, '/');
169 32 : }
170 :
171 33 : static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
172 : void *data;
173 : unsigned i;
174 : int r;
175 :
176 33 : assert(m);
177 33 : assert(bloom);
178 :
179 33 : data = bloom->data;
180 33 : memzero(data, m->bus->bloom_size);
181 33 : bloom->generation = 0;
182 :
183 33 : bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
184 :
185 33 : if (m->interface)
186 33 : bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
187 33 : if (m->member)
188 33 : bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
189 33 : if (m->path) {
190 33 : bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
191 33 : bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
192 33 : bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
193 : }
194 :
195 33 : r = sd_bus_message_rewind(m, true);
196 33 : if (r < 0)
197 0 : return r;
198 :
199 70 : for (i = 0; i < 64; i++) {
200 : const char *t, *contents;
201 : char type;
202 :
203 35 : r = sd_bus_message_peek_type(m, &type, &contents);
204 35 : if (r < 0)
205 0 : return r;
206 :
207 35 : if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
208 :
209 : /* The bloom filter includes simple strings of any kind */
210 30 : r = sd_bus_message_read_basic(m, type, &t);
211 30 : if (r < 0)
212 0 : return r;
213 :
214 30 : add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
215 35 : } if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
216 :
217 : /* As well as array of simple strings of any kinds */
218 2 : r = sd_bus_message_enter_container(m, type, contents);
219 2 : if (r < 0)
220 0 : return r;
221 :
222 6 : while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0)
223 2 : add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
224 2 : if (r < 0)
225 0 : return r;
226 :
227 2 : r = sd_bus_message_exit_container(m);
228 2 : if (r < 0)
229 0 : return r;
230 :
231 : } else
232 : /* Stop adding to bloom filter as soon as we
233 : * run into the first argument we cannot add
234 : * to it. */
235 : break;
236 : }
237 :
238 33 : return 0;
239 : }
240 :
241 15531 : static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
242 : struct bus_body_part *part;
243 : struct kdbus_item *d;
244 : const char *destination;
245 : bool well_known;
246 : uint64_t unique;
247 : size_t sz, dl;
248 : unsigned i;
249 : int r;
250 :
251 15531 : assert(b);
252 15531 : assert(m);
253 15531 : assert(m->sealed);
254 :
255 : /* We put this together only once, if this message is reused
256 : * we reuse the earlier-built version */
257 15531 : if (m->kdbus)
258 0 : return 0;
259 :
260 15531 : destination = m->destination ?: m->destination_ptr;
261 :
262 15531 : if (destination) {
263 15498 : r = bus_kernel_parse_unique_name(destination, &unique);
264 15498 : if (r < 0)
265 0 : return r;
266 :
267 15498 : well_known = r == 0;
268 : } else
269 33 : well_known = false;
270 :
271 15531 : sz = offsetof(struct kdbus_msg, items);
272 :
273 : /* Add in fixed header, fields header and payload */
274 15531 : sz += (1 + m->n_body_parts) * ALIGN8(offsetof(struct kdbus_item, vec) +
275 : MAX(sizeof(struct kdbus_vec),
276 : sizeof(struct kdbus_memfd)));
277 :
278 : /* Add space for bloom filter */
279 15531 : sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) +
280 : offsetof(struct kdbus_bloom_filter, data) +
281 : m->bus->bloom_size);
282 :
283 : /* Add in well-known destination header */
284 15531 : if (well_known) {
285 10 : dl = strlen(destination);
286 10 : sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
287 : }
288 :
289 : /* Add space for unix fds */
290 15531 : if (m->n_fds > 0)
291 2 : sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
292 :
293 15531 : m->kdbus = memalign(8, sz);
294 15531 : if (!m->kdbus) {
295 0 : r = -ENOMEM;
296 0 : goto fail;
297 : }
298 :
299 15531 : m->free_kdbus = true;
300 15531 : memzero(m->kdbus, sz);
301 :
302 31062 : m->kdbus->flags =
303 31062 : ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
304 31062 : ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0) |
305 15531 : ((m->header->type == SD_BUS_MESSAGE_SIGNAL) ? KDBUS_MSG_SIGNAL : 0);
306 :
307 15531 : if (well_known)
308 : /* verify_destination_id will usually be 0, which makes the kernel driver only look
309 : * at the provided well-known name. Otherwise, the kernel will make sure the provided
310 : * destination id matches the owner of the provided weel-known-name, and fail if they
311 : * differ. Currently, this is only needed for bus-proxyd. */
312 10 : m->kdbus->dst_id = m->verify_destination_id;
313 : else
314 15521 : m->kdbus->dst_id = destination ? unique : KDBUS_DST_ID_BROADCAST;
315 :
316 15531 : m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
317 15531 : m->kdbus->cookie = m->header->dbus2.cookie;
318 15531 : m->kdbus->priority = m->priority;
319 :
320 15531 : if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
321 15524 : m->kdbus->cookie_reply = m->reply_cookie;
322 : else {
323 : struct timespec now;
324 :
325 7 : assert_se(clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == 0);
326 14 : m->kdbus->timeout_ns = now.tv_sec * NSEC_PER_SEC + now.tv_nsec +
327 7 : m->timeout * NSEC_PER_USEC;
328 : }
329 :
330 15531 : d = m->kdbus->items;
331 :
332 15531 : if (well_known)
333 10 : append_destination(&d, destination, dl);
334 :
335 15531 : append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
336 :
337 31069 : MESSAGE_FOREACH_PART(part, i, m) {
338 15538 : if (part->is_zero) {
339 : /* If this is padding then simply send a
340 : * vector with a NULL data pointer which the
341 : * kernel will just pass through. This is the
342 : * most efficient way to encode zeroes */
343 :
344 1 : append_payload_vec(&d, NULL, part->size);
345 1 : continue;
346 : }
347 :
348 15537 : if (part->memfd >= 0 && part->sealed && destination) {
349 : /* Try to send a memfd, if the part is
350 : * sealed and this is not a broadcast. Since we can only */
351 :
352 3 : append_payload_memfd(&d, part->memfd, part->memfd_offset, part->size);
353 3 : continue;
354 : }
355 :
356 : /* Otherwise, let's send a vector to the actual data.
357 : * For that, we need to map it first. */
358 15534 : r = bus_body_part_map(part);
359 15534 : if (r < 0)
360 0 : goto fail;
361 :
362 15534 : append_payload_vec(&d, part->data, part->size);
363 : }
364 :
365 15531 : if (m->header->type == SD_BUS_MESSAGE_SIGNAL) {
366 : struct kdbus_bloom_filter *bloom;
367 :
368 33 : bloom = append_bloom(&d, m->bus->bloom_size);
369 33 : r = bus_message_setup_bloom(m, bloom);
370 33 : if (r < 0)
371 0 : goto fail;
372 : }
373 :
374 15531 : if (m->n_fds > 0)
375 2 : append_fds(&d, m->fds, m->n_fds);
376 :
377 15531 : m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
378 15531 : assert(m->kdbus->size <= sz);
379 :
380 15531 : return 0;
381 :
382 : fail:
383 0 : m->poisoned = true;
384 0 : return r;
385 : }
386 :
387 0 : static void unset_memfds(struct sd_bus_message *m) {
388 : struct bus_body_part *part;
389 : unsigned i;
390 :
391 0 : assert(m);
392 :
393 : /* Make sure the memfds are not freed twice */
394 0 : MESSAGE_FOREACH_PART(part, i, m)
395 0 : if (part->memfd >= 0)
396 0 : part->memfd = -1;
397 0 : }
398 :
399 6 : static void message_set_timestamp(sd_bus *bus, sd_bus_message *m, const struct kdbus_timestamp *ts) {
400 6 : assert(bus);
401 6 : assert(m);
402 :
403 6 : if (!ts)
404 0 : return;
405 :
406 6 : if (!(bus->attach_flags & KDBUS_ATTACH_TIMESTAMP))
407 4 : return;
408 :
409 2 : m->realtime = ts->realtime_ns / NSEC_PER_USEC;
410 2 : m->monotonic = ts->monotonic_ns / NSEC_PER_USEC;
411 2 : m->seqnum = ts->seqnum;
412 : }
413 :
414 15516 : static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
415 15516 : sd_bus_message *m = NULL;
416 : struct kdbus_item *d;
417 15516 : unsigned n_fds = 0;
418 31031 : _cleanup_free_ int *fds = NULL;
419 15516 : struct bus_header *header = NULL;
420 15516 : void *footer = NULL;
421 15516 : size_t header_size = 0, footer_size = 0;
422 15516 : size_t n_bytes = 0, idx = 0;
423 15516 : const char *destination = NULL, *seclabel = NULL;
424 15516 : bool last_was_memfd = false;
425 : int r;
426 :
427 15516 : assert(bus);
428 15516 : assert(k);
429 15516 : assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
430 :
431 61245 : KDBUS_ITEM_FOREACH(d, k, items) {
432 : size_t l;
433 :
434 45729 : l = d->size - offsetof(struct kdbus_item, data);
435 :
436 45729 : switch (d->type) {
437 :
438 : case KDBUS_ITEM_PAYLOAD_OFF:
439 38326 : if (!header) {
440 15516 : header = (struct bus_header*)((uint8_t*) k + d->vec.offset);
441 15516 : header_size = d->vec.size;
442 : }
443 :
444 38326 : footer = (uint8_t*) k + d->vec.offset;
445 38326 : footer_size = d->vec.size;
446 :
447 38326 : n_bytes += d->vec.size;
448 38326 : last_was_memfd = false;
449 38326 : break;
450 :
451 : case KDBUS_ITEM_PAYLOAD_MEMFD:
452 7347 : if (!header) /* memfd cannot be first part */
453 0 : return -EBADMSG;
454 :
455 7347 : n_bytes += d->memfd.size;
456 7347 : last_was_memfd = true;
457 7347 : break;
458 :
459 : case KDBUS_ITEM_FDS: {
460 : int *f;
461 : unsigned j;
462 :
463 2 : j = l / sizeof(int);
464 2 : f = realloc(fds, sizeof(int) * (n_fds + j));
465 2 : if (!f)
466 0 : return -ENOMEM;
467 :
468 2 : fds = f;
469 2 : memcpy(fds + n_fds, d->fds, sizeof(int) * j);
470 2 : n_fds += j;
471 2 : break;
472 : }
473 :
474 : case KDBUS_ITEM_SECLABEL:
475 0 : seclabel = d->str;
476 0 : break;
477 : }
478 : }
479 :
480 15516 : if (last_was_memfd) /* memfd cannot be last part */
481 0 : return -EBADMSG;
482 :
483 15516 : if (!header)
484 0 : return -EBADMSG;
485 :
486 15516 : if (header_size < sizeof(struct bus_header))
487 0 : return -EBADMSG;
488 :
489 : /* on kdbus we only speak native endian gvariant, never dbus1
490 : * marshalling or reverse endian */
491 31032 : if (header->version != 2 ||
492 15516 : header->endian != BUS_NATIVE_ENDIAN)
493 0 : return -EPROTOTYPE;
494 :
495 15516 : r = bus_message_from_header(
496 : bus,
497 : header, header_size,
498 : footer, footer_size,
499 : n_bytes,
500 : fds, n_fds,
501 : seclabel, 0, &m);
502 15516 : if (r < 0)
503 0 : return r;
504 :
505 : /* The well-known names list is different from the other
506 : credentials. If we asked for it, but nothing is there, this
507 : means that the list of well-known names is simply empty, not
508 : that we lack any data */
509 :
510 15516 : m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
511 :
512 61245 : KDBUS_ITEM_FOREACH(d, k, items) {
513 : size_t l;
514 :
515 45729 : l = d->size - offsetof(struct kdbus_item, data);
516 :
517 45729 : switch (d->type) {
518 :
519 : case KDBUS_ITEM_PAYLOAD_OFF: {
520 : size_t begin_body;
521 :
522 38326 : begin_body = BUS_MESSAGE_BODY_BEGIN(m);
523 :
524 38326 : if (idx + d->vec.size > begin_body) {
525 : struct bus_body_part *part;
526 :
527 : /* Contains body material */
528 :
529 22810 : part = message_append_part(m);
530 22810 : if (!part) {
531 0 : r = -ENOMEM;
532 0 : goto fail;
533 : }
534 :
535 : /* A -1 offset is NUL padding. */
536 22810 : part->is_zero = d->vec.offset == ~0ULL;
537 :
538 22810 : if (idx >= begin_body) {
539 22810 : if (!part->is_zero)
540 22810 : part->data = (uint8_t* )k + d->vec.offset;
541 22810 : part->size = d->vec.size;
542 : } else {
543 0 : if (!part->is_zero)
544 0 : part->data = (uint8_t*) k + d->vec.offset + (begin_body - idx);
545 0 : part->size = d->vec.size - (begin_body - idx);
546 : }
547 :
548 22810 : part->sealed = true;
549 : }
550 :
551 38326 : idx += d->vec.size;
552 38326 : break;
553 : }
554 :
555 : case KDBUS_ITEM_PAYLOAD_MEMFD: {
556 : struct bus_body_part *part;
557 :
558 7347 : if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
559 0 : r = -EBADMSG;
560 0 : goto fail;
561 : }
562 :
563 7347 : part = message_append_part(m);
564 7347 : if (!part) {
565 0 : r = -ENOMEM;
566 0 : goto fail;
567 : }
568 :
569 7347 : part->memfd = d->memfd.fd;
570 7347 : part->memfd_offset = d->memfd.start;
571 7347 : part->size = d->memfd.size;
572 7347 : part->sealed = true;
573 :
574 7347 : idx += d->memfd.size;
575 7347 : break;
576 : }
577 :
578 : case KDBUS_ITEM_PIDS:
579 :
580 : /* The PID/TID might be missing, when the data
581 : * is faked by a bus proxy and it lacks that
582 : * information about the real client (since
583 : * SO_PEERCRED is used for that). Also kernel
584 : * namespacing might make some of this data
585 : * unavailable when untranslatable. */
586 :
587 2 : if (d->pids.pid > 0) {
588 2 : m->creds.pid = (pid_t) d->pids.pid;
589 2 : m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
590 : }
591 :
592 2 : if (d->pids.tid > 0) {
593 2 : m->creds.tid = (pid_t) d->pids.tid;
594 2 : m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
595 : }
596 :
597 2 : if (d->pids.ppid > 0) {
598 2 : m->creds.ppid = (pid_t) d->pids.ppid;
599 2 : m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
600 0 : } else if (d->pids.pid == 1) {
601 0 : m->creds.ppid = 0;
602 0 : m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
603 : }
604 :
605 2 : break;
606 :
607 : case KDBUS_ITEM_CREDS:
608 :
609 : /* EUID/SUID/FSUID/EGID/SGID/FSGID might be
610 : * missing too (see above). */
611 :
612 2 : if ((uid_t) d->creds.uid != UID_INVALID) {
613 2 : m->creds.uid = (uid_t) d->creds.uid;
614 2 : m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
615 : }
616 :
617 2 : if ((uid_t) d->creds.euid != UID_INVALID) {
618 2 : m->creds.euid = (uid_t) d->creds.euid;
619 2 : m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
620 : }
621 :
622 2 : if ((uid_t) d->creds.suid != UID_INVALID) {
623 2 : m->creds.suid = (uid_t) d->creds.suid;
624 2 : m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
625 : }
626 :
627 2 : if ((uid_t) d->creds.fsuid != UID_INVALID) {
628 2 : m->creds.fsuid = (uid_t) d->creds.fsuid;
629 2 : m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
630 : }
631 :
632 2 : if ((gid_t) d->creds.gid != GID_INVALID) {
633 2 : m->creds.gid = (gid_t) d->creds.gid;
634 2 : m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
635 : }
636 :
637 2 : if ((gid_t) d->creds.egid != GID_INVALID) {
638 2 : m->creds.egid = (gid_t) d->creds.egid;
639 2 : m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
640 : }
641 :
642 2 : if ((gid_t) d->creds.sgid != GID_INVALID) {
643 2 : m->creds.sgid = (gid_t) d->creds.sgid;
644 2 : m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
645 : }
646 :
647 2 : if ((gid_t) d->creds.fsgid != GID_INVALID) {
648 2 : m->creds.fsgid = (gid_t) d->creds.fsgid;
649 2 : m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
650 : }
651 :
652 2 : break;
653 :
654 : case KDBUS_ITEM_TIMESTAMP:
655 2 : message_set_timestamp(bus, m, &d->timestamp);
656 2 : break;
657 :
658 : case KDBUS_ITEM_PID_COMM:
659 2 : m->creds.comm = d->str;
660 2 : m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
661 2 : break;
662 :
663 : case KDBUS_ITEM_TID_COMM:
664 2 : m->creds.tid_comm = d->str;
665 2 : m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
666 2 : break;
667 :
668 : case KDBUS_ITEM_EXE:
669 2 : m->creds.exe = d->str;
670 2 : m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
671 2 : break;
672 :
673 : case KDBUS_ITEM_CMDLINE:
674 2 : m->creds.cmdline = d->str;
675 2 : m->creds.cmdline_size = l;
676 2 : m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
677 2 : break;
678 :
679 : case KDBUS_ITEM_CGROUP:
680 2 : m->creds.cgroup = d->str;
681 2 : m->creds.mask |= (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) & bus->creds_mask;
682 :
683 2 : r = bus_get_root_path(bus);
684 2 : if (r < 0)
685 0 : goto fail;
686 :
687 2 : m->creds.cgroup_root = bus->cgroup_root;
688 2 : break;
689 :
690 : case KDBUS_ITEM_AUDIT:
691 0 : m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
692 0 : m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
693 :
694 0 : m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
695 0 : m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
696 0 : break;
697 :
698 : case KDBUS_ITEM_CAPS:
699 4 : if (d->caps.last_cap != cap_last_cap() ||
700 2 : d->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(d->caps.last_cap, 32U) * 4 * 4) {
701 0 : r = -EBADMSG;
702 0 : goto fail;
703 : }
704 :
705 2 : m->creds.capability = d->caps.caps;
706 2 : m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
707 2 : break;
708 :
709 : case KDBUS_ITEM_DST_NAME:
710 9 : if (!service_name_is_valid(d->str)) {
711 0 : r = -EBADMSG;
712 0 : goto fail;
713 : }
714 :
715 9 : destination = d->str;
716 9 : break;
717 :
718 : case KDBUS_ITEM_OWNED_NAME:
719 3 : if (!service_name_is_valid(d->name.name)) {
720 0 : r = -EBADMSG;
721 0 : goto fail;
722 : }
723 :
724 3 : if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
725 : char **wkn;
726 : size_t n;
727 :
728 : /* We just extend the array here, but
729 : * do not allocate the strings inside
730 : * of it, instead we just point to our
731 : * buffer directly. */
732 3 : n = strv_length(m->creds.well_known_names);
733 3 : wkn = realloc(m->creds.well_known_names, (n + 2) * sizeof(char*));
734 3 : if (!wkn) {
735 0 : r = -ENOMEM;
736 0 : goto fail;
737 : }
738 :
739 3 : wkn[n] = d->name.name;
740 3 : wkn[n+1] = NULL;
741 3 : m->creds.well_known_names = wkn;
742 :
743 3 : m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
744 : }
745 3 : break;
746 :
747 : case KDBUS_ITEM_CONN_DESCRIPTION:
748 2 : m->creds.description = d->str;
749 2 : m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
750 2 : break;
751 :
752 : case KDBUS_ITEM_AUXGROUPS:
753 :
754 2 : if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
755 : size_t i, n;
756 : gid_t *g;
757 :
758 2 : n = (d->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
759 2 : g = new(gid_t, n);
760 2 : if (!g) {
761 0 : r = -ENOMEM;
762 0 : goto fail;
763 : }
764 :
765 8 : for (i = 0; i < n; i++)
766 6 : g[i] = d->data64[i];
767 :
768 2 : m->creds.supplementary_gids = g;
769 2 : m->creds.n_supplementary_gids = n;
770 2 : m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
771 : }
772 :
773 2 : break;
774 :
775 : case KDBUS_ITEM_FDS:
776 : case KDBUS_ITEM_SECLABEL:
777 2 : break;
778 :
779 : default:
780 20 : log_debug("Got unknown field from kernel %llu", d->type);
781 : }
782 : }
783 :
784 : /* If we requested the list of well-known names to be appended
785 : * and the sender had none no item for it will be
786 : * attached. However, this does *not* mean that the kernel
787 : * didn't want to provide this information to us. Hence, let's
788 : * explicitly mark this information as available if it was
789 : * requested. */
790 15516 : m->creds.mask |= bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
791 :
792 15516 : r = bus_message_parse_fields(m);
793 15516 : if (r < 0)
794 0 : goto fail;
795 :
796 : /* Refuse messages if kdbus and dbus1 cookie doesn't match up */
797 15516 : if ((uint64_t) m->header->dbus2.cookie != k->cookie) {
798 0 : r = -EBADMSG;
799 0 : goto fail;
800 : }
801 :
802 : /* Refuse messages where the reply flag doesn't match up */
803 15516 : if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_EXPECT_REPLY)) {
804 0 : r = -EBADMSG;
805 0 : goto fail;
806 : }
807 :
808 : /* Refuse reply messages where the reply cookie doesn't match up */
809 15516 : if ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) && m->reply_cookie != k->cookie_reply) {
810 0 : r = -EBADMSG;
811 0 : goto fail;
812 : }
813 :
814 : /* Refuse messages where the autostart flag doesn't match up */
815 15516 : if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_NO_AUTO_START)) {
816 0 : r = -EBADMSG;
817 0 : goto fail;
818 : }
819 :
820 : /* Override information from the user header with data from the kernel */
821 15516 : if (k->src_id == KDBUS_SRC_ID_KERNEL)
822 0 : bus_message_set_sender_driver(bus, m);
823 : else {
824 15516 : snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
825 15516 : m->sender = m->creds.unique_name = m->sender_buffer;
826 : }
827 :
828 15515 : if (destination)
829 8 : m->destination = destination;
830 15507 : else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
831 20 : m->destination = NULL;
832 15487 : else if (k->dst_id == KDBUS_DST_ID_NAME)
833 0 : m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
834 : else {
835 15487 : snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
836 15487 : m->destination = m->destination_buffer;
837 : }
838 :
839 : /* We take possession of the kmsg struct now */
840 15515 : m->kdbus = k;
841 15515 : m->release_kdbus = true;
842 15515 : m->free_fds = true;
843 15515 : fds = NULL;
844 :
845 15515 : bus->rqueue[bus->rqueue_size++] = m;
846 :
847 15515 : return 1;
848 :
849 : fail:
850 0 : unset_memfds(m);
851 0 : sd_bus_message_unref(m);
852 :
853 0 : return r;
854 : }
855 :
856 76 : int bus_kernel_take_fd(sd_bus *b) {
857 76 : struct kdbus_bloom_parameter *bloom = NULL;
858 : struct kdbus_item *items, *item;
859 : struct kdbus_cmd_hello *hello;
860 152 : _cleanup_free_ char *g = NULL;
861 : const char *name;
862 76 : size_t l = 0, m = 0, sz;
863 : int r;
864 :
865 76 : assert(b);
866 :
867 76 : if (b->is_server)
868 0 : return -EINVAL;
869 :
870 76 : b->use_memfd = 1;
871 :
872 76 : if (b->description) {
873 1 : g = bus_label_escape(b->description);
874 1 : if (!g)
875 0 : return -ENOMEM;
876 :
877 1 : name = g;
878 : } else {
879 75 : char pr[17] = {};
880 :
881 : /* If no name is explicitly set, we'll include a hint
882 : * indicating the library implementation, a hint which
883 : * kind of bus this is and the thread name */
884 :
885 75 : assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
886 :
887 74 : if (isempty(pr)) {
888 0 : name = b->is_system ? "sd-system" :
889 0 : b->is_user ? "sd-user" : "sd";
890 : } else {
891 148 : _cleanup_free_ char *e = NULL;
892 :
893 74 : e = bus_label_escape(pr);
894 75 : if (!e)
895 0 : return -ENOMEM;
896 :
897 144 : g = strappend(b->is_system ? "sd-system-" :
898 69 : b->is_user ? "sd-user-" : "sd-",
899 : e);
900 74 : if (!g)
901 0 : return -ENOMEM;
902 :
903 74 : name = g;
904 : }
905 :
906 74 : b->description = bus_label_unescape(name);
907 75 : if (!b->description)
908 0 : return -ENOMEM;
909 : }
910 :
911 76 : m = strlen(name);
912 :
913 76 : sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
914 76 : ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
915 :
916 76 : if (b->fake_creds_valid)
917 0 : sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
918 :
919 76 : if (b->fake_pids_valid)
920 0 : sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
921 :
922 76 : if (b->fake_label) {
923 0 : l = strlen(b->fake_label);
924 0 : sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
925 : }
926 :
927 76 : hello = alloca0_align(sz, 8);
928 76 : hello->size = sz;
929 76 : hello->flags = b->hello_flags;
930 76 : hello->attach_flags_send = _KDBUS_ATTACH_ANY;
931 76 : hello->attach_flags_recv = b->attach_flags;
932 76 : hello->pool_size = KDBUS_POOL_SIZE;
933 :
934 76 : item = hello->items;
935 :
936 76 : item->size = offsetof(struct kdbus_item, str) + m + 1;
937 76 : item->type = KDBUS_ITEM_CONN_DESCRIPTION;
938 76 : memcpy(item->str, name, m + 1);
939 76 : item = KDBUS_ITEM_NEXT(item);
940 :
941 76 : if (b->fake_creds_valid) {
942 0 : item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
943 0 : item->type = KDBUS_ITEM_CREDS;
944 0 : item->creds = b->fake_creds;
945 :
946 0 : item = KDBUS_ITEM_NEXT(item);
947 : }
948 :
949 76 : if (b->fake_pids_valid) {
950 0 : item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
951 0 : item->type = KDBUS_ITEM_PIDS;
952 0 : item->pids = b->fake_pids;
953 :
954 0 : item = KDBUS_ITEM_NEXT(item);
955 : }
956 :
957 76 : if (b->fake_label) {
958 0 : item->size = offsetof(struct kdbus_item, str) + l + 1;
959 0 : item->type = KDBUS_ITEM_SECLABEL;
960 0 : memcpy(item->str, b->fake_label, l+1);
961 : }
962 :
963 76 : r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
964 76 : if (r < 0) {
965 0 : if (errno == ENOTTY)
966 : /* If the ioctl is not supported we assume that the
967 : * API version changed in a major incompatible way,
968 : * let's indicate an API incompatibility in this
969 : * case. */
970 0 : return -ESOCKTNOSUPPORT;
971 :
972 0 : return -errno;
973 : }
974 :
975 76 : if (!b->kdbus_buffer) {
976 76 : b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
977 76 : if (b->kdbus_buffer == MAP_FAILED) {
978 0 : b->kdbus_buffer = NULL;
979 0 : r = -errno;
980 0 : goto fail;
981 : }
982 : }
983 :
984 : /* The higher 32bit of the bus_flags fields are considered
985 : * 'incompatible flags'. Refuse them all for now. */
986 76 : if (hello->bus_flags > 0xFFFFFFFFULL) {
987 0 : r = -ESOCKTNOSUPPORT;
988 0 : goto fail;
989 : }
990 :
991 : /* extract bloom parameters from items */
992 76 : items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset);
993 152 : KDBUS_FOREACH(item, items, hello->items_size) {
994 76 : switch (item->type) {
995 : case KDBUS_ITEM_BLOOM_PARAMETER:
996 76 : bloom = &item->bloom_parameter;
997 76 : break;
998 : }
999 : }
1000 :
1001 76 : if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) {
1002 0 : r = -EOPNOTSUPP;
1003 0 : goto fail;
1004 : }
1005 :
1006 76 : b->bloom_size = (size_t) bloom->size;
1007 76 : b->bloom_n_hash = (unsigned) bloom->n_hash;
1008 :
1009 76 : if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) {
1010 0 : r = -ENOMEM;
1011 0 : goto fail;
1012 : }
1013 :
1014 76 : b->unique_id = hello->id;
1015 :
1016 76 : b->is_kernel = true;
1017 76 : b->bus_client = true;
1018 76 : b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
1019 76 : b->message_version = 2;
1020 76 : b->message_endian = BUS_NATIVE_ENDIAN;
1021 :
1022 : /* the kernel told us the UUID of the underlying bus */
1023 76 : memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
1024 :
1025 : /* free returned items */
1026 76 : (void) bus_kernel_cmd_free(b, hello->offset);
1027 76 : return bus_start_running(b);
1028 :
1029 : fail:
1030 0 : (void) bus_kernel_cmd_free(b, hello->offset);
1031 0 : return r;
1032 : }
1033 :
1034 76 : int bus_kernel_connect(sd_bus *b) {
1035 76 : assert(b);
1036 76 : assert(b->input_fd < 0);
1037 76 : assert(b->output_fd < 0);
1038 76 : assert(b->kernel);
1039 :
1040 76 : if (b->is_server)
1041 0 : return -EINVAL;
1042 :
1043 76 : b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
1044 75 : if (b->input_fd < 0)
1045 0 : return -errno;
1046 :
1047 75 : b->output_fd = b->input_fd;
1048 :
1049 75 : return bus_kernel_take_fd(b);
1050 : }
1051 :
1052 15597 : int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) {
1053 15597 : struct kdbus_cmd_free cmd = {
1054 : .size = sizeof(cmd),
1055 : .offset = offset,
1056 : };
1057 : int r;
1058 :
1059 15597 : assert(bus);
1060 15597 : assert(bus->is_kernel);
1061 :
1062 15597 : r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
1063 15597 : if (r < 0)
1064 1 : return -errno;
1065 :
1066 15596 : return 0;
1067 : }
1068 :
1069 4 : static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
1070 : struct kdbus_item *d;
1071 :
1072 4 : assert(bus);
1073 4 : assert(k);
1074 :
1075 12 : KDBUS_ITEM_FOREACH(d, k, items) {
1076 8 : if (d->type == KDBUS_ITEM_FDS)
1077 0 : close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
1078 8 : else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
1079 0 : safe_close(d->memfd.fd);
1080 : }
1081 :
1082 4 : bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer);
1083 4 : }
1084 :
1085 15531 : int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
1086 15531 : struct kdbus_cmd_send cmd = { };
1087 : int r;
1088 :
1089 15531 : assert(bus);
1090 15531 : assert(m);
1091 15531 : assert(bus->state == BUS_RUNNING);
1092 :
1093 : /* If we can't deliver, we want room for the error message */
1094 15531 : r = bus_rqueue_make_room(bus);
1095 15531 : if (r < 0)
1096 0 : return r;
1097 :
1098 15531 : r = bus_message_setup_kmsg(bus, m);
1099 15531 : if (r < 0)
1100 0 : return r;
1101 :
1102 15531 : cmd.size = sizeof(cmd);
1103 15531 : cmd.msg_address = (uintptr_t)m->kdbus;
1104 :
1105 : /* If this is a synchronous method call, then let's tell the
1106 : * kernel, so that it can pass CPU time/scheduling to the
1107 : * destination for the time, if it wants to. If we
1108 : * synchronously wait for the result anyway, we won't need CPU
1109 : * anyway. */
1110 15531 : if (hint_sync_call) {
1111 5 : m->kdbus->flags |= KDBUS_MSG_EXPECT_REPLY;
1112 5 : cmd.flags |= KDBUS_SEND_SYNC_REPLY;
1113 : }
1114 :
1115 15531 : r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
1116 15531 : if (r < 0) {
1117 8 : _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1118 : sd_bus_message *reply;
1119 :
1120 4 : if (errno == EAGAIN || errno == EINTR)
1121 0 : return 0;
1122 4 : else if (errno == ENXIO || errno == ESRCH) {
1123 :
1124 : /* ENXIO: unique name not known
1125 : * ESRCH: well-known name not known */
1126 :
1127 4 : if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1128 1 : sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
1129 : else {
1130 2 : log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
1131 2 : return 0;
1132 : }
1133 :
1134 1 : } else if (errno == EADDRNOTAVAIL) {
1135 :
1136 : /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
1137 :
1138 0 : if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1139 0 : sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
1140 : else {
1141 0 : log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
1142 0 : return 0;
1143 : }
1144 : } else
1145 1 : return -errno;
1146 :
1147 1 : r = bus_message_new_synthetic_error(
1148 : bus,
1149 : BUS_MESSAGE_COOKIE(m),
1150 : &error,
1151 : &reply);
1152 :
1153 1 : if (r < 0)
1154 0 : return r;
1155 :
1156 1 : r = bus_seal_synthetic_message(bus, reply);
1157 1 : if (r < 0)
1158 0 : return r;
1159 :
1160 1 : bus->rqueue[bus->rqueue_size++] = reply;
1161 :
1162 15527 : } else if (hint_sync_call) {
1163 : struct kdbus_msg *k;
1164 :
1165 3 : k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + cmd.reply.offset);
1166 3 : assert(k);
1167 :
1168 3 : if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
1169 :
1170 3 : r = bus_kernel_make_message(bus, k);
1171 3 : if (r < 0) {
1172 0 : close_kdbus_msg(bus, k);
1173 :
1174 : /* Anybody can send us invalid messages, let's just drop them. */
1175 0 : if (r == -EBADMSG || r == -EPROTOTYPE)
1176 0 : log_debug_errno(r, "Ignoring invalid synchronous reply: %m");
1177 : else
1178 0 : return r;
1179 : }
1180 : } else {
1181 0 : log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
1182 0 : close_kdbus_msg(bus, k);
1183 : }
1184 : }
1185 :
1186 15528 : return 1;
1187 : }
1188 :
1189 3 : static int push_name_owner_changed(
1190 : sd_bus *bus,
1191 : const char *name,
1192 : const char *old_owner,
1193 : const char *new_owner,
1194 : const struct kdbus_timestamp *ts) {
1195 :
1196 6 : _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1197 : int r;
1198 :
1199 3 : assert(bus);
1200 :
1201 3 : r = sd_bus_message_new_signal(
1202 : bus,
1203 : &m,
1204 : "/org/freedesktop/DBus",
1205 : "org.freedesktop.DBus",
1206 : "NameOwnerChanged");
1207 3 : if (r < 0)
1208 0 : return r;
1209 :
1210 3 : r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
1211 3 : if (r < 0)
1212 0 : return r;
1213 :
1214 3 : bus_message_set_sender_driver(bus, m);
1215 3 : message_set_timestamp(bus, m, ts);
1216 :
1217 3 : r = bus_seal_synthetic_message(bus, m);
1218 3 : if (r < 0)
1219 0 : return r;
1220 :
1221 3 : bus->rqueue[bus->rqueue_size++] = m;
1222 3 : m = NULL;
1223 :
1224 3 : return 1;
1225 : }
1226 :
1227 0 : static int translate_name_change(
1228 : sd_bus *bus,
1229 : const struct kdbus_msg *k,
1230 : const struct kdbus_item *d,
1231 : const struct kdbus_timestamp *ts) {
1232 :
1233 : char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
1234 :
1235 0 : assert(bus);
1236 0 : assert(k);
1237 0 : assert(d);
1238 :
1239 0 : if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
1240 0 : old_owner[0] = 0;
1241 : else
1242 0 : sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id.id);
1243 :
1244 0 : if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
1245 :
1246 0 : if (isempty(old_owner))
1247 0 : return 0;
1248 :
1249 0 : new_owner[0] = 0;
1250 : } else
1251 0 : sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id.id);
1252 :
1253 0 : return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ts);
1254 : }
1255 :
1256 3 : static int translate_id_change(
1257 : sd_bus *bus,
1258 : const struct kdbus_msg *k,
1259 : const struct kdbus_item *d,
1260 : const struct kdbus_timestamp *ts) {
1261 :
1262 : char owner[UNIQUE_NAME_MAX];
1263 :
1264 3 : assert(bus);
1265 3 : assert(k);
1266 3 : assert(d);
1267 :
1268 3 : sprintf(owner, ":1.%llu", d->id_change.id);
1269 :
1270 6 : return push_name_owner_changed(
1271 : bus, owner,
1272 3 : d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
1273 3 : d->type == KDBUS_ITEM_ID_ADD ? owner : NULL,
1274 : ts);
1275 : }
1276 :
1277 1 : static int translate_reply(
1278 : sd_bus *bus,
1279 : const struct kdbus_msg *k,
1280 : const struct kdbus_item *d,
1281 : const struct kdbus_timestamp *ts) {
1282 :
1283 2 : _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1284 : int r;
1285 :
1286 1 : assert(bus);
1287 1 : assert(k);
1288 1 : assert(d);
1289 :
1290 3 : r = bus_message_new_synthetic_error(
1291 : bus,
1292 1 : k->cookie_reply,
1293 1 : d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
1294 1 : &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
1295 0 : &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
1296 : &m);
1297 1 : if (r < 0)
1298 0 : return r;
1299 :
1300 1 : message_set_timestamp(bus, m, ts);
1301 :
1302 1 : r = bus_seal_synthetic_message(bus, m);
1303 1 : if (r < 0)
1304 0 : return r;
1305 :
1306 1 : bus->rqueue[bus->rqueue_size++] = m;
1307 1 : m = NULL;
1308 :
1309 1 : return 1;
1310 : }
1311 :
1312 4 : static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
1313 : static int (* const translate[])(sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) = {
1314 : [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1315 : [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1316 : [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1317 :
1318 : [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
1319 : [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
1320 :
1321 : [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
1322 : [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
1323 : };
1324 :
1325 4 : struct kdbus_item *d, *found = NULL;
1326 4 : struct kdbus_timestamp *ts = NULL;
1327 :
1328 4 : assert(bus);
1329 4 : assert(k);
1330 4 : assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
1331 :
1332 12 : KDBUS_ITEM_FOREACH(d, k, items) {
1333 8 : if (d->type == KDBUS_ITEM_TIMESTAMP)
1334 4 : ts = &d->timestamp;
1335 4 : else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
1336 4 : if (found)
1337 0 : return -EBADMSG;
1338 4 : found = d;
1339 : } else
1340 0 : log_debug("Got unknown field from kernel %llu", d->type);
1341 : }
1342 :
1343 4 : if (!found) {
1344 0 : log_debug("Didn't find a kernel message to translate.");
1345 0 : return 0;
1346 : }
1347 :
1348 4 : return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found, ts);
1349 : }
1350 :
1351 31018 : int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
1352 31018 : struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
1353 : struct kdbus_msg *k;
1354 : int r;
1355 :
1356 31018 : assert(bus);
1357 :
1358 31018 : r = bus_rqueue_make_room(bus);
1359 31018 : if (r < 0)
1360 0 : return r;
1361 :
1362 31018 : if (hint_priority) {
1363 1 : recv.flags |= KDBUS_RECV_USE_PRIORITY;
1364 1 : recv.priority = priority;
1365 : }
1366 :
1367 31018 : r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv);
1368 31018 : if (recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS)
1369 0 : log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
1370 31018 : if (r < 0) {
1371 15501 : if (errno == EAGAIN)
1372 15501 : return 0;
1373 :
1374 0 : return -errno;
1375 : }
1376 :
1377 15517 : k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.msg.offset);
1378 15517 : if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
1379 15513 : r = bus_kernel_make_message(bus, k);
1380 :
1381 : /* Anybody can send us invalid messages, let's just drop them. */
1382 15513 : if (r == -EBADMSG || r == -EPROTOTYPE) {
1383 0 : log_debug_errno(r, "Ignoring invalid message: %m");
1384 0 : r = 0;
1385 : }
1386 :
1387 15513 : if (r <= 0)
1388 0 : close_kdbus_msg(bus, k);
1389 4 : } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) {
1390 4 : r = bus_kernel_translate_message(bus, k);
1391 4 : close_kdbus_msg(bus, k);
1392 : } else {
1393 0 : log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
1394 0 : r = 0;
1395 0 : close_kdbus_msg(bus, k);
1396 : }
1397 :
1398 15517 : return r < 0 ? r : 1;
1399 : }
1400 :
1401 15578 : int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
1402 : struct memfd_cache *c;
1403 : int fd;
1404 :
1405 15578 : assert(address);
1406 15578 : assert(mapped);
1407 15578 : assert(allocated);
1408 :
1409 15578 : if (!bus || !bus->is_kernel)
1410 35 : return -EOPNOTSUPP;
1411 :
1412 15543 : assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
1413 :
1414 15544 : if (bus->n_memfd_cache <= 0) {
1415 : int r;
1416 :
1417 46 : assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1418 :
1419 46 : r = memfd_new(bus->description);
1420 46 : if (r < 0)
1421 0 : return r;
1422 :
1423 46 : *address = NULL;
1424 46 : *mapped = 0;
1425 46 : *allocated = 0;
1426 46 : return r;
1427 : }
1428 :
1429 15498 : c = &bus->memfd_cache[--bus->n_memfd_cache];
1430 :
1431 15498 : assert(c->fd >= 0);
1432 15498 : assert(c->mapped == 0 || c->address);
1433 :
1434 15498 : *address = c->address;
1435 15498 : *mapped = c->mapped;
1436 15498 : *allocated = c->allocated;
1437 15498 : fd = c->fd;
1438 :
1439 15498 : assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1440 :
1441 15498 : return fd;
1442 : }
1443 :
1444 46 : static void close_and_munmap(int fd, void *address, size_t size) {
1445 46 : if (size > 0)
1446 46 : assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
1447 :
1448 46 : safe_close(fd);
1449 46 : }
1450 :
1451 15544 : void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
1452 : struct memfd_cache *c;
1453 15544 : uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
1454 :
1455 15544 : assert(fd >= 0);
1456 15544 : assert(mapped == 0 || address);
1457 :
1458 15544 : if (!bus || !bus->is_kernel) {
1459 0 : close_and_munmap(fd, address, mapped);
1460 0 : return;
1461 : }
1462 :
1463 15544 : assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
1464 :
1465 15544 : if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
1466 0 : assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1467 :
1468 0 : close_and_munmap(fd, address, mapped);
1469 0 : return;
1470 : }
1471 :
1472 15544 : c = &bus->memfd_cache[bus->n_memfd_cache++];
1473 15544 : c->fd = fd;
1474 15544 : c->address = address;
1475 :
1476 : /* If overly long, let's return a bit to the OS */
1477 15544 : if (mapped > max_mapped) {
1478 0 : assert_se(memfd_set_size(fd, max_mapped) >= 0);
1479 0 : assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
1480 0 : c->mapped = c->allocated = max_mapped;
1481 : } else {
1482 15544 : c->mapped = mapped;
1483 15544 : c->allocated = allocated;
1484 : }
1485 :
1486 15544 : assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1487 : }
1488 :
1489 94 : void bus_kernel_flush_memfd(sd_bus *b) {
1490 : unsigned i;
1491 :
1492 94 : assert(b);
1493 :
1494 140 : for (i = 0; i < b->n_memfd_cache; i++)
1495 46 : close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
1496 94 : }
1497 :
1498 2 : uint64_t request_name_flags_to_kdbus(uint64_t flags) {
1499 2 : uint64_t f = 0;
1500 :
1501 2 : if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1502 0 : f |= KDBUS_NAME_ALLOW_REPLACEMENT;
1503 :
1504 2 : if (flags & SD_BUS_NAME_REPLACE_EXISTING)
1505 0 : f |= KDBUS_NAME_REPLACE_EXISTING;
1506 :
1507 2 : if (flags & SD_BUS_NAME_QUEUE)
1508 0 : f |= KDBUS_NAME_QUEUE;
1509 :
1510 2 : return f;
1511 : }
1512 :
1513 3 : uint64_t attach_flags_to_kdbus(uint64_t mask) {
1514 3 : uint64_t m = 0;
1515 :
1516 3 : if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
1517 : SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
1518 2 : m |= KDBUS_ATTACH_CREDS;
1519 :
1520 3 : if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID))
1521 2 : m |= KDBUS_ATTACH_PIDS;
1522 :
1523 3 : if (mask & SD_BUS_CREDS_COMM)
1524 2 : m |= KDBUS_ATTACH_PID_COMM;
1525 :
1526 3 : if (mask & SD_BUS_CREDS_TID_COMM)
1527 2 : m |= KDBUS_ATTACH_TID_COMM;
1528 :
1529 3 : if (mask & SD_BUS_CREDS_EXE)
1530 2 : m |= KDBUS_ATTACH_EXE;
1531 :
1532 3 : if (mask & SD_BUS_CREDS_CMDLINE)
1533 2 : m |= KDBUS_ATTACH_CMDLINE;
1534 :
1535 3 : if (mask & (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))
1536 2 : m |= KDBUS_ATTACH_CGROUP;
1537 :
1538 3 : if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
1539 2 : m |= KDBUS_ATTACH_CAPS;
1540 :
1541 3 : if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
1542 2 : m |= KDBUS_ATTACH_SECLABEL;
1543 :
1544 3 : if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
1545 2 : m |= KDBUS_ATTACH_AUDIT;
1546 :
1547 3 : if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
1548 3 : m |= KDBUS_ATTACH_NAMES;
1549 :
1550 3 : if (mask & SD_BUS_CREDS_DESCRIPTION)
1551 2 : m |= KDBUS_ATTACH_CONN_DESCRIPTION;
1552 :
1553 3 : if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
1554 2 : m |= KDBUS_ATTACH_AUXGROUPS;
1555 :
1556 3 : return m;
1557 : }
1558 :
1559 34 : int bus_kernel_create_bus(const char *name, bool world, char **s) {
1560 : struct kdbus_cmd *make;
1561 : struct kdbus_item *n;
1562 : size_t l;
1563 : int fd;
1564 :
1565 34 : assert(name);
1566 34 : assert(s);
1567 :
1568 34 : fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
1569 34 : if (fd < 0)
1570 0 : return -errno;
1571 :
1572 34 : l = strlen(name);
1573 34 : make = alloca0_align(offsetof(struct kdbus_cmd, items) +
1574 : ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) +
1575 : ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
1576 : ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1),
1577 : 8);
1578 :
1579 34 : make->size = offsetof(struct kdbus_cmd, items);
1580 :
1581 : /* Set the bloom parameters */
1582 34 : n = make->items;
1583 34 : n->size = offsetof(struct kdbus_item, bloom_parameter) +
1584 : sizeof(struct kdbus_bloom_parameter);
1585 34 : n->type = KDBUS_ITEM_BLOOM_PARAMETER;
1586 34 : n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
1587 34 : n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
1588 :
1589 : assert_cc(DEFAULT_BLOOM_SIZE > 0);
1590 : assert_cc(DEFAULT_BLOOM_N_HASH > 0);
1591 :
1592 34 : make->size += ALIGN8(n->size);
1593 :
1594 : /* Provide all metadata via bus-owner queries */
1595 34 : n = KDBUS_ITEM_NEXT(n);
1596 34 : n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
1597 34 : n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
1598 34 : n->data64[0] = _KDBUS_ATTACH_ANY;
1599 34 : make->size += ALIGN8(n->size);
1600 :
1601 : /* Set the a good name */
1602 34 : n = KDBUS_ITEM_NEXT(n);
1603 34 : sprintf(n->str, UID_FMT "-%s", getuid(), name);
1604 34 : n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
1605 34 : n->type = KDBUS_ITEM_MAKE_NAME;
1606 34 : make->size += ALIGN8(n->size);
1607 :
1608 34 : make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
1609 :
1610 34 : if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
1611 0 : safe_close(fd);
1612 :
1613 : /* Major API change? then the ioctls got shuffled around. */
1614 0 : if (errno == ENOTTY)
1615 0 : return -ESOCKTNOSUPPORT;
1616 :
1617 0 : return -errno;
1618 : }
1619 :
1620 34 : if (s) {
1621 : char *p;
1622 :
1623 34 : p = strjoin("/sys/fs/kdbus/", n->str, "/bus", NULL);
1624 34 : if (!p) {
1625 0 : safe_close(fd);
1626 0 : return -ENOMEM;
1627 : }
1628 :
1629 34 : *s = p;
1630 : }
1631 :
1632 34 : return fd;
1633 : }
1634 :
1635 0 : int bus_kernel_open_bus_fd(const char *bus, char **path) {
1636 : char *p;
1637 : int fd;
1638 : size_t len;
1639 :
1640 0 : assert(bus);
1641 :
1642 0 : len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
1643 :
1644 0 : if (path) {
1645 0 : p = new(char, len);
1646 0 : if (!p)
1647 0 : return -ENOMEM;
1648 : } else
1649 0 : p = newa(char, len);
1650 :
1651 0 : sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
1652 :
1653 0 : fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
1654 0 : if (fd < 0) {
1655 0 : if (path)
1656 0 : free(p);
1657 :
1658 0 : return -errno;
1659 : }
1660 :
1661 0 : if (path)
1662 0 : *path = p;
1663 :
1664 0 : return fd;
1665 : }
1666 :
1667 0 : int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) {
1668 0 : _cleanup_free_ char *path = NULL;
1669 : struct kdbus_cmd *make;
1670 : struct kdbus_item *n;
1671 : const char *name;
1672 : int fd;
1673 :
1674 0 : fd = bus_kernel_open_bus_fd(bus_name, &path);
1675 0 : if (fd < 0)
1676 0 : return fd;
1677 :
1678 0 : make = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd, items)) +
1679 : ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + strlen(ep_name) + 1),
1680 : 8);
1681 0 : make->size = ALIGN8(offsetof(struct kdbus_cmd, items));
1682 0 : make->flags = KDBUS_MAKE_ACCESS_WORLD;
1683 :
1684 0 : n = make->items;
1685 0 : sprintf(n->str, UID_FMT "-%s", getuid(), ep_name);
1686 0 : n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
1687 0 : n->type = KDBUS_ITEM_MAKE_NAME;
1688 0 : make->size += ALIGN8(n->size);
1689 0 : name = n->str;
1690 :
1691 0 : if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) {
1692 0 : safe_close(fd);
1693 0 : return -errno;
1694 : }
1695 :
1696 0 : if (ep_path) {
1697 : char *p;
1698 :
1699 0 : p = strjoin(dirname(path), "/", name, NULL);
1700 0 : if (!p) {
1701 0 : safe_close(fd);
1702 0 : return -ENOMEM;
1703 : }
1704 :
1705 0 : *ep_path = p;
1706 : }
1707 :
1708 0 : return fd;
1709 : }
1710 :
1711 2 : int bus_kernel_try_close(sd_bus *bus) {
1712 2 : struct kdbus_cmd byebye = { .size = sizeof(byebye) };
1713 :
1714 2 : assert(bus);
1715 2 : assert(bus->is_kernel);
1716 :
1717 2 : if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE, &byebye) < 0)
1718 1 : return -errno;
1719 :
1720 1 : return 0;
1721 : }
1722 :
1723 0 : int bus_kernel_drop_one(int fd) {
1724 0 : struct kdbus_cmd_recv recv = {
1725 : .size = sizeof(recv),
1726 : .flags = KDBUS_RECV_DROP,
1727 : };
1728 :
1729 0 : assert(fd >= 0);
1730 :
1731 0 : if (ioctl(fd, KDBUS_CMD_RECV, &recv) < 0)
1732 0 : return -errno;
1733 :
1734 0 : return 0;
1735 : }
1736 :
1737 2 : int bus_kernel_realize_attach_flags(sd_bus *bus) {
1738 : struct kdbus_cmd *update;
1739 : struct kdbus_item *n;
1740 :
1741 2 : assert(bus);
1742 2 : assert(bus->is_kernel);
1743 :
1744 2 : update = alloca0_align(offsetof(struct kdbus_cmd, items) +
1745 : ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)),
1746 : 8);
1747 :
1748 2 : n = update->items;
1749 2 : n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
1750 2 : n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
1751 2 : n->data64[0] = bus->attach_flags;
1752 :
1753 2 : update->size =
1754 2 : offsetof(struct kdbus_cmd, items) +
1755 2 : ALIGN8(n->size);
1756 :
1757 2 : if (ioctl(bus->input_fd, KDBUS_CMD_UPDATE, update) < 0)
1758 0 : return -errno;
1759 :
1760 2 : return 0;
1761 : }
1762 :
1763 1 : int bus_kernel_get_bus_name(sd_bus *bus, char **name) {
1764 1 : struct kdbus_cmd_info cmd = {
1765 : .size = sizeof(struct kdbus_cmd_info),
1766 : };
1767 : struct kdbus_info *info;
1768 : struct kdbus_item *item;
1769 1 : char *n = NULL;
1770 : int r;
1771 :
1772 1 : assert(bus);
1773 1 : assert(name);
1774 1 : assert(bus->is_kernel);
1775 :
1776 1 : r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
1777 1 : if (r < 0)
1778 0 : return -errno;
1779 :
1780 1 : info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset);
1781 :
1782 1 : KDBUS_ITEM_FOREACH(item, info, items)
1783 1 : if (item->type == KDBUS_ITEM_MAKE_NAME) {
1784 1 : r = free_and_strdup(&n, item->str);
1785 1 : break;
1786 : }
1787 :
1788 1 : bus_kernel_cmd_free(bus, cmd.offset);
1789 :
1790 1 : if (r < 0)
1791 0 : return r;
1792 1 : if (!n)
1793 0 : return -EIO;
1794 :
1795 1 : *name = n;
1796 1 : return 0;
1797 : }
|