]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-kernel.c
util: unify SO_PEERCRED/SO_PEERSEC invocations
[thirdparty/systemd.git] / src / libsystemd-bus / bus-kernel.c
CommitLineData
6629161f
LP
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
7211f918
LP
22#ifdef HAVE_VALGRIND_MEMCHECK_H
23#include <valgrind/memcheck.h>
24#endif
25
6629161f 26#include <fcntl.h>
c556fe79 27#include <malloc.h>
fd8d62d9 28#include <sys/mman.h>
6629161f
LP
29
30#include "util.h"
65dae17a 31#include "strv.h"
6629161f
LP
32
33#include "bus-internal.h"
34#include "bus-message.h"
35#include "bus-kernel.h"
a56f19c4 36#include "bus-bloom.h"
777d7a61
LP
37#include "bus-util.h"
38
39#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
6629161f 40
c7819669 41int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
6629161f
LP
42 int r;
43
44 assert(s);
45 assert(id);
46
47 if (!startswith(s, ":1."))
48 return 0;
49
50 r = safe_atou64(s + 3, id);
51 if (r < 0)
52 return r;
53
54 return 1;
55}
56
febfd508 57static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
6629161f 58 assert(d);
6629161f
LP
59 assert(sz > 0);
60
e86b80b8
LP
61 *d = ALIGN8_PTR(*d);
62
66b26c5c
LP
63 /* Note that p can be NULL, which encodes a region full of
64 * zeroes, which is useful to optimize certain padding
65 * conditions */
66
febfd508 67 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
ea1edece 68 (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
a392d361 69 (*d)->vec.address = PTR_TO_UINT64(p);
6629161f
LP
70 (*d)->vec.size = sz;
71
febfd508 72 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
6629161f
LP
73}
74
a392d361
LP
75static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
76 assert(d);
77 assert(memfd >= 0);
78 assert(sz > 0);
79
80 *d = ALIGN8_PTR(*d);
81 (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
ea1edece 82 (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
a392d361
LP
83 (*d)->memfd.fd = memfd;
84 (*d)->memfd.size = sz;
85
86 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
87}
88
febfd508 89static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
6629161f 90 assert(d);
b5baa8fe 91 assert(s);
6629161f 92
e86b80b8
LP
93 *d = ALIGN8_PTR(*d);
94
febfd508 95 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
ea1edece 96 (*d)->type = KDBUS_ITEM_DST_NAME;
51038c03 97 memcpy((*d)->str, s, length + 1);
6629161f 98
febfd508 99 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
6629161f
LP
100}
101
febfd508 102static void* append_bloom(struct kdbus_item **d, size_t length) {
a56f19c4
LP
103 void *r;
104
b5baa8fe 105 assert(d);
b5baa8fe
LP
106
107 *d = ALIGN8_PTR(*d);
108
febfd508 109 (*d)->size = offsetof(struct kdbus_item, data) + length;
ea1edece 110 (*d)->type = KDBUS_ITEM_BLOOM;
a56f19c4 111 r = (*d)->data;
b5baa8fe 112
febfd508 113 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
a56f19c4
LP
114
115 return r;
116}
117
febfd508 118static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
9097fe29
LP
119 assert(d);
120 assert(fds);
121 assert(n_fds > 0);
122
123 *d = ALIGN8_PTR(*d);
febfd508 124 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
ea1edece 125 (*d)->type = KDBUS_ITEM_FDS;
9097fe29
LP
126 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
127
febfd508 128 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
9097fe29
LP
129}
130
a56f19c4
LP
131static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
132 unsigned i;
133 int r;
134
135 assert(m);
136 assert(bloom);
137
138 memset(bloom, 0, BLOOM_SIZE);
139
140 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
141
142 if (m->interface)
143 bloom_add_pair(bloom, "interface", m->interface);
144 if (m->member)
145 bloom_add_pair(bloom, "member", m->member);
146 if (m->path) {
147 bloom_add_pair(bloom, "path", m->path);
f11e11e3 148 bloom_add_pair(bloom, "path-slash-prefix", m->path);
a56f19c4
LP
149 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
150 }
151
152 r = sd_bus_message_rewind(m, true);
153 if (r < 0)
154 return r;
155
156 for (i = 0; i < 64; i++) {
157 char type;
158 const char *t;
159 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
160 char *e;
161
162 r = sd_bus_message_peek_type(m, &type, NULL);
163 if (r < 0)
164 return r;
165
166 if (type != SD_BUS_TYPE_STRING &&
167 type != SD_BUS_TYPE_OBJECT_PATH &&
168 type != SD_BUS_TYPE_SIGNATURE)
169 break;
170
171 r = sd_bus_message_read_basic(m, type, &t);
172 if (r < 0)
173 return r;
174
175 e = stpcpy(buf, "arg");
176 if (i < 10)
177 *(e++) = '0' + i;
178 else {
179 *(e++) = '0' + (i / 10);
180 *(e++) = '0' + (i % 10);
181 }
182
183 *e = 0;
184 bloom_add_pair(bloom, buf, t);
185
186 strcpy(e, "-dot-prefix");
187 bloom_add_prefixes(bloom, buf, t, '.');
188 strcpy(e, "-slash-prefix");
189 bloom_add_prefixes(bloom, buf, t, '/');
190 }
191
192 return 0;
b5baa8fe
LP
193}
194
5b7d4c1c 195static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
9b29bb68 196 struct bus_body_part *part;
febfd508 197 struct kdbus_item *d;
6629161f
LP
198 bool well_known;
199 uint64_t unique;
200 size_t sz, dl;
9b29bb68 201 unsigned i;
6629161f
LP
202 int r;
203
5b7d4c1c 204 assert(b);
6629161f
LP
205 assert(m);
206 assert(m->sealed);
e9a967f9
LP
207
208 if (m->kdbus)
209 return 0;
6629161f
LP
210
211 if (m->destination) {
c7819669 212 r = bus_kernel_parse_unique_name(m->destination, &unique);
6629161f
LP
213 if (r < 0)
214 return r;
215
216 well_known = r == 0;
217 } else
218 well_known = false;
219
b1454bf0 220 sz = offsetof(struct kdbus_msg, items);
6629161f 221
a392d361
LP
222 assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
223 ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
224
69aec65c 225 /* Add in fixed header, fields header and payload */
c91cb83c 226 sz += (1 + m->n_body_parts) *
bc7fd8cd 227 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
6629161f 228
69aec65c 229 /* Add space for bloom filter */
febfd508 230 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
b5baa8fe 231
6629161f
LP
232 /* Add in well-known destination header */
233 if (well_known) {
234 dl = strlen(m->destination);
febfd508 235 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
6629161f
LP
236 }
237
9097fe29
LP
238 /* Add space for unix fds */
239 if (m->n_fds > 0)
febfd508 240 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
9097fe29 241
c556fe79 242 m->kdbus = memalign(8, sz);
66b26c5c
LP
243 if (!m->kdbus) {
244 r = -ENOMEM;
245 goto fail;
246 }
6629161f 247
66b26c5c 248 m->free_kdbus = true;
d9115e18
LP
249 memset(m->kdbus, 0, sz);
250
6629161f 251 m->kdbus->flags =
0461f8cd
LP
252 ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
253 ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
6629161f
LP
254 m->kdbus->dst_id =
255 well_known ? 0 :
b5baa8fe 256 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
6647dc66 257 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
6629161f
LP
258 m->kdbus->cookie = m->header->serial;
259
260 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
261
b1454bf0 262 d = m->kdbus->items;
6629161f
LP
263
264 if (well_known)
265 append_destination(&d, m->destination, dl);
266
c91cb83c 267 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
a392d361
LP
268
269 MESSAGE_FOREACH_PART(part, i, m) {
270 if (part->is_zero) {
66b26c5c
LP
271 /* If this is padding then simply send a
272 * vector with a NULL data pointer which the
273 * kernel will just pass through. This is the
274 * most efficient way to encode zeroes */
275
a392d361
LP
276 append_payload_vec(&d, NULL, part->size);
277 continue;
278 }
279
66b26c5c
LP
280 if (part->memfd >= 0 && part->sealed && m->destination) {
281 /* Try to send a memfd, if the part is
282 * sealed and this is not a broadcast. Since we can only */
a392d361 283
66b26c5c
LP
284 append_payload_memfd(&d, part->memfd, part->size);
285 continue;
a392d361
LP
286 }
287
66b26c5c
LP
288 /* Otherwise let's send a vector to the actual data,
289 * for that we need to map it first. */
290 r = bus_body_part_map(part);
291 if (r < 0)
292 goto fail;
a392d361 293
bc7fd8cd 294 append_payload_vec(&d, part->data, part->size);
a392d361 295 }
6629161f 296
5b7d4c1c
LP
297 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
298 void *p;
299
a56f19c4
LP
300 p = append_bloom(&d, BLOOM_SIZE);
301 r = bus_message_setup_bloom(m, p);
a392d361
LP
302 if (r < 0)
303 goto fail;
5b7d4c1c 304 }
b5baa8fe 305
9097fe29
LP
306 if (m->n_fds > 0)
307 append_fds(&d, m->fds, m->n_fds);
308
e9a967f9 309 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
6629161f
LP
310 assert(m->kdbus->size <= sz);
311
312 return 0;
a392d361
LP
313
314fail:
66b26c5c 315 m->poisoned = true;
a392d361 316 return r;
6629161f
LP
317}
318
319int bus_kernel_take_fd(sd_bus *b) {
8a0e0ed9
LP
320 struct kdbus_cmd_hello *hello;
321 struct kdbus_item *item;
aedd330b 322 size_t l = 0, sz;
6629161f
LP
323 int r;
324
325 assert(b);
35460afc
LP
326
327 if (b->is_server)
328 return -EINVAL;
f08838da 329
8f155917
LP
330 b->use_memfd = 1;
331
8a0e0ed9 332 sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items));
62b3e928 333
8a0e0ed9 334 if (b->fake_creds_valid)
96415cad 335 sz += ALIGN8(offsetof(struct kdbus_item, creds)) + sizeof(struct kdbus_creds);
8a0e0ed9
LP
336
337 if (b->fake_label) {
338 l = strlen(b->fake_label);
339 sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
340 }
341
342 hello = alloca0(sz);
343 hello->size = sz;
344 hello->conn_flags = b->hello_flags;
345 hello->attach_flags = b->attach_flags;
346 hello->pool_size = KDBUS_POOL_SIZE;
347
348 item = hello->items;
349
350 if (b->fake_creds_valid) {
351 item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
352 item->type = KDBUS_ITEM_CREDS;
353 item->creds = b->fake_creds;
354
355 item = KDBUS_ITEM_NEXT(item);
356 }
357
358 if (b->fake_label) {
359 item->size = offsetof(struct kdbus_item, str) + l + 1;
360 memcpy(item->str, b->fake_label, l+1);
361 }
362
363 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
62b3e928
KS
364 if (r < 0)
365 return -errno;
366
fd8d62d9 367 if (!b->kdbus_buffer) {
62b3e928 368 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
fd8d62d9
LP
369 if (b->kdbus_buffer == MAP_FAILED) {
370 b->kdbus_buffer = NULL;
371 return -errno;
372 }
373 }
374
5b7d4c1c
LP
375 /* The higher 32bit of both flags fields are considered
376 * 'incompatible flags'. Refuse them all for now. */
8a0e0ed9
LP
377 if (hello->bus_flags > 0xFFFFFFFFULL ||
378 hello->conn_flags > 0xFFFFFFFFULL)
5b7d4c1c
LP
379 return -ENOTSUP;
380
8a0e0ed9 381 if (hello->bloom_size != BLOOM_SIZE)
a56f19c4
LP
382 return -ENOTSUP;
383
8a0e0ed9 384 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
de297575
LP
385 return -ENOMEM;
386
8a0e0ed9 387 b->unique_id = hello->id;
219728b3 388
6629161f 389 b->is_kernel = true;
f08838da 390 b->bus_client = true;
8a0e0ed9 391 b->can_fds = !!(hello->conn_flags & KDBUS_HELLO_ACCEPT_FD);
e1d337d4 392 b->message_version = 2;
0f437184 393 b->message_endian = BUS_NATIVE_ENDIAN;
6629161f 394
c58dea19 395 /* the kernel told us the UUID of the underlying bus */
8a0e0ed9 396 memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
c58dea19 397
7adc46fc 398 return bus_start_running(b);
6629161f
LP
399}
400
401int bus_kernel_connect(sd_bus *b) {
402 assert(b);
403 assert(b->input_fd < 0);
404 assert(b->output_fd < 0);
405 assert(b->kernel);
35460afc
LP
406
407 if (b->is_server)
408 return -EINVAL;
f08838da 409
6629161f 410 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
c320885c 411 if (b->input_fd < 0)
6629161f
LP
412 return -errno;
413
414 b->output_fd = b->input_fd;
415
416 return bus_kernel_take_fd(b);
417}
418
419int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
420 int r;
421
422 assert(bus);
423 assert(m);
424 assert(bus->state == BUS_RUNNING);
425
a43b9ca3
LP
426 /* If we can't deliver, we want room for the error message */
427 r = bus_rqueue_make_room(bus);
428 if (r < 0)
429 return r;
430
5b7d4c1c 431 r = bus_message_setup_kmsg(bus, m);
6629161f
LP
432 if (r < 0)
433 return r;
434
435 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
a43b9ca3
LP
436 if (r < 0) {
437 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
438 sd_bus_message *reply;
439
440 if (errno == EAGAIN || errno == EINTR)
441 return 0;
442 else if (errno == ENXIO || errno == ESRCH) {
443
444 /* ENXIO: unique name not known
445 * ESRCH: well-known name not known */
446
447 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
448 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
ff4994c5
LP
449 else {
450 log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
a43b9ca3 451 return 0;
ff4994c5 452 }
a43b9ca3
LP
453
454 } else if (errno == EADDRNOTAVAIL) {
455
456 /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
457
458 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
459 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
ff4994c5
LP
460 else {
461 log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
a43b9ca3 462 return 0;
ff4994c5 463 }
a43b9ca3
LP
464 } else
465 return -errno;
466
467 r = bus_message_new_synthetic_error(
468 bus,
469 BUS_MESSAGE_SERIAL(m),
470 &error,
471 &reply);
472
473 if (r < 0)
474 return r;
475
476 r = bus_seal_synthetic_message(bus, reply);
477 if (r < 0)
478 return r;
479
480 bus->rqueue[bus->rqueue_size++] = reply;
481
482 return 0;
483 }
6629161f 484
51038c03 485 return 1;
6629161f
LP
486}
487
fd8d62d9 488static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
62b3e928 489 uint64_t off;
febfd508 490 struct kdbus_item *d;
6629161f 491
fd8d62d9
LP
492 assert(bus);
493 assert(k);
494
62b3e928 495 off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
1d0e3c98 496 ioctl(bus->input_fd, KDBUS_CMD_FREE, &off);
fd8d62d9 497
a8d4cac5 498 KDBUS_ITEM_FOREACH(d, k, items) {
6629161f 499
ea1edece 500 if (d->type == KDBUS_ITEM_FDS)
1307c3ff 501 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
ea1edece 502 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
1307c3ff 503 close_nointr_nofail(d->memfd.fd);
6629161f
LP
504 }
505}
506
7d22c717 507static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) {
777d7a61
LP
508 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
509 int r;
510
511 assert(bus);
777d7a61
LP
512
513 r = sd_bus_message_new_signal(
514 bus,
515 "/org/freedesktop/DBus",
516 "org.freedesktop.DBus",
517 "NameOwnerChanged",
518 &m);
519 if (r < 0)
520 return r;
521
522 r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
523 if (r < 0)
524 return r;
525
526 m->sender = "org.freedesktop.DBus";
527
7adc46fc 528 r = bus_seal_synthetic_message(bus, m);
7d22c717
LP
529 if (r < 0)
530 return r;
777d7a61 531
7adc46fc 532 bus->rqueue[bus->rqueue_size++] = m;
7d22c717 533 m = NULL;
219728b3 534
219728b3
LP
535 return 1;
536}
537
7d22c717 538static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
777d7a61
LP
539 char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
540
541 assert(bus);
542 assert(k);
543 assert(d);
777d7a61 544
ceceaf09 545 if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
777d7a61
LP
546 old_owner[0] = 0;
547 else
ceceaf09 548 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old.id);
777d7a61 549
ceceaf09 550 if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
d78bf250
LP
551
552 if (isempty(old_owner))
553 return 0;
554
777d7a61 555 new_owner[0] = 0;
d78bf250 556 } else
ceceaf09 557 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new.id);
777d7a61 558
7d22c717 559 return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner);
777d7a61
LP
560}
561
7d22c717 562static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
777d7a61
LP
563 char owner[UNIQUE_NAME_MAX];
564
565 assert(bus);
566 assert(k);
567 assert(d);
777d7a61
LP
568
569 sprintf(owner, ":1.%llu", d->id_change.id);
570
7d22c717 571 return push_name_owner_changed(
777d7a61
LP
572 bus, owner,
573 d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
7d22c717 574 d->type == KDBUS_ITEM_ID_ADD ? owner : NULL);
777d7a61
LP
575}
576
7d22c717 577static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
777d7a61
LP
578 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
579 int r;
580
581 assert(bus);
582 assert(k);
583 assert(d);
777d7a61
LP
584
585 r = bus_message_new_synthetic_error(
586 bus,
587 k->cookie_reply,
588 d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
589 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
590 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
591 &m);
592 if (r < 0)
593 return r;
594
595 m->sender = "org.freedesktop.DBus";
596
7adc46fc 597 r = bus_seal_synthetic_message(bus, m);
7d22c717
LP
598 if (r < 0)
599 return r;
777d7a61 600
7adc46fc 601 bus->rqueue[bus->rqueue_size++] = m;
7d22c717 602 m = NULL;
7adc46fc 603
777d7a61
LP
604 return 1;
605}
606
7d22c717 607static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
777d7a61
LP
608 struct kdbus_item *d, *found = NULL;
609
7d22c717 610 static int (* const translate[])(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) = {
777d7a61
LP
611 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
612 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
613 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
614
615 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
616 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
617
618 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
619 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
620 };
621
622 assert(bus);
623 assert(k);
777d7a61
LP
624 assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
625
a8d4cac5 626 KDBUS_ITEM_FOREACH(d, k, items) {
777d7a61
LP
627 if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
628 if (found)
629 return -EBADMSG;
630 found = d;
631 } else
632 log_debug("Got unknown field from kernel %llu", d->type);
633 }
634
635 if (!found) {
636 log_debug("Didn't find a kernel message to translate.");
637 return 0;
638 }
639
51502af3 640 return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found);
777d7a61
LP
641}
642
7d22c717 643static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
6629161f 644 sd_bus_message *m = NULL;
febfd508 645 struct kdbus_item *d;
1307c3ff 646 unsigned n_fds = 0;
6629161f
LP
647 _cleanup_free_ int *fds = NULL;
648 struct bus_header *h = NULL;
649 size_t total, n_bytes = 0, idx = 0;
69aec65c 650 const char *destination = NULL, *seclabel = NULL;
6629161f
LP
651 int r;
652
653 assert(bus);
654 assert(k);
6647dc66 655 assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
6629161f 656
a8d4cac5 657 KDBUS_ITEM_FOREACH(d, k, items) {
6629161f
LP
658 size_t l;
659
febfd508 660 l = d->size - offsetof(struct kdbus_item, data);
6629161f 661
777d7a61 662 switch (d->type) {
6629161f 663
777d7a61 664 case KDBUS_ITEM_PAYLOAD_OFF:
6629161f 665 if (!h) {
ec76ec1f 666 h = (struct bus_header *)((uint8_t *)k + d->vec.offset);
c91cb83c
LP
667
668 if (!bus_header_is_complete(h, d->vec.size))
669 return -EBADMSG;
6629161f
LP
670 }
671
fd8d62d9 672 n_bytes += d->vec.size;
777d7a61 673 break;
6629161f 674
777d7a61 675 case KDBUS_ITEM_PAYLOAD_MEMFD:
1307c3ff
LP
676 if (!h)
677 return -EBADMSG;
678
679 n_bytes += d->memfd.size;
777d7a61 680 break;
1307c3ff 681
777d7a61 682 case KDBUS_ITEM_FDS: {
6629161f
LP
683 int *f;
684 unsigned j;
685
686 j = l / sizeof(int);
687 f = realloc(fds, sizeof(int) * (n_fds + j));
688 if (!f)
689 return -ENOMEM;
690
691 fds = f;
9097fe29 692 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
6629161f 693 n_fds += j;
777d7a61
LP
694 break;
695 }
f9be01f3 696
777d7a61 697 case KDBUS_ITEM_SECLABEL:
69aec65c 698 seclabel = d->str;
777d7a61
LP
699 break;
700 }
6629161f
LP
701 }
702
703 if (!h)
704 return -EBADMSG;
705
c91cb83c 706 r = bus_header_message_size(h, &total);
6629161f
LP
707 if (r < 0)
708 return r;
709
710 if (n_bytes != total)
711 return -EBADMSG;
712
e1d337d4
LP
713 /* on kdbus we only speak native endian gvariant, never dbus1
714 * marshalling or reverse endian */
715 if (h->version != 2 ||
716 h->endian != BUS_NATIVE_ENDIAN)
717 return -EPROTOTYPE;
718
df2d202e 719 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
6629161f
LP
720 if (r < 0)
721 return r;
722
253ce82b
LP
723 /* The well-known names list is different from the other
724 credentials. If we asked for it, but nothing is there, this
725 means that the list of well-known names is simply empty, not
726 that we lack any data */
727
728 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
729
a8d4cac5 730 KDBUS_ITEM_FOREACH(d, k, items) {
6629161f
LP
731 size_t l;
732
febfd508 733 l = d->size - offsetof(struct kdbus_item, data);
6629161f 734
777d7a61
LP
735 switch (d->type) {
736
737 case KDBUS_ITEM_PAYLOAD_OFF: {
bc7fd8cd 738 size_t begin_body;
fd8d62d9 739
c91cb83c 740 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
bc7fd8cd
LP
741
742 if (idx + d->vec.size > begin_body) {
743 struct bus_body_part *part;
744
745 /* Contains body material */
746
747 part = message_append_part(m);
748 if (!part) {
1307c3ff
LP
749 r = -ENOMEM;
750 goto fail;
bc7fd8cd
LP
751 }
752
62b3e928
KS
753 /* A -1 offset is NUL padding. */
754 part->is_zero = d->vec.offset == ~0ULL;
755
bc7fd8cd 756 if (idx >= begin_body) {
62b3e928 757 if (!part->is_zero)
ec76ec1f 758 part->data = (uint8_t *)k + d->vec.offset;
bc7fd8cd
LP
759 part->size = d->vec.size;
760 } else {
62b3e928 761 if (!part->is_zero)
ec76ec1f 762 part->data = (uint8_t *)k + d->vec.offset + (begin_body - idx);
bc7fd8cd
LP
763 part->size = d->vec.size - (begin_body - idx);
764 }
765
766 part->sealed = true;
767 }
fd8d62d9
LP
768
769 idx += d->vec.size;
777d7a61
LP
770 break;
771 }
772
773 case KDBUS_ITEM_PAYLOAD_MEMFD: {
1307c3ff
LP
774 struct bus_body_part *part;
775
776 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
777 r = -EBADMSG;
778 goto fail;
779 }
780
781 part = message_append_part(m);
782 if (!part) {
783 r = -ENOMEM;
784 goto fail;
785 }
786
787 part->memfd = d->memfd.fd;
788 part->size = d->memfd.size;
789 part->sealed = true;
790
791 idx += d->memfd.size;
777d7a61
LP
792 break;
793 }
69aec65c 794
777d7a61 795 case KDBUS_ITEM_CREDS:
5b12334d
LP
796 m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
797 m->creds.uid = d->creds.uid;
798 m->creds.gid = d->creds.gid;
799 m->creds.pid = d->creds.pid;
800 m->creds.tid = d->creds.tid;
801 m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID) & bus->creds_mask;
777d7a61 802 break;
5b12334d 803
777d7a61 804 case KDBUS_ITEM_TIMESTAMP:
69aec65c
LP
805 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
806 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
777d7a61 807 break;
5b12334d 808
777d7a61 809 case KDBUS_ITEM_PID_COMM:
5b12334d
LP
810 m->creds.comm = d->str;
811 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
777d7a61 812 break;
5b12334d 813
777d7a61 814 case KDBUS_ITEM_TID_COMM:
5b12334d
LP
815 m->creds.tid_comm = d->str;
816 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
777d7a61 817 break;
5b12334d 818
777d7a61 819 case KDBUS_ITEM_EXE:
5b12334d
LP
820 m->creds.exe = d->str;
821 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
777d7a61 822 break;
5b12334d 823
777d7a61 824 case KDBUS_ITEM_CMDLINE:
5b12334d 825 m->creds.cmdline = d->str;
49b832c5 826 m->creds.cmdline_size = l;
5b12334d 827 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
777d7a61 828 break;
5b12334d 829
777d7a61 830 case KDBUS_ITEM_CGROUP:
5b12334d
LP
831 m->creds.cgroup = d->str;
832 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;
777d7a61 833 break;
5b12334d 834
777d7a61 835 case KDBUS_ITEM_AUDIT:
5b12334d
LP
836 m->creds.audit_session_id = d->audit.sessionid;
837 m->creds.audit_login_uid = d->audit.loginuid;
838 m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
777d7a61 839 break;
5b12334d 840
777d7a61 841 case KDBUS_ITEM_CAPS:
5b12334d
LP
842 m->creds.capability = d->data;
843 m->creds.capability_size = l;
844 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;
777d7a61 845 break;
5b12334d 846
777d7a61 847 case KDBUS_ITEM_DST_NAME:
1307c3ff 848 destination = d->str;
777d7a61
LP
849 break;
850
65dae17a
KS
851 case KDBUS_ITEM_NAME:
852 r = strv_extend(&m->creds.well_known_names, d->name.name);
853 if (r < 0)
854 goto fail;
49b832c5
LP
855 break;
856
777d7a61
LP
857 case KDBUS_ITEM_FDS:
858 case KDBUS_ITEM_SECLABEL:
777d7a61
LP
859 break;
860
861 default:
77930f11 862 log_debug("Got unknown field from kernel %llu", d->type);
777d7a61 863 }
69aec65c 864 }
acb5a3cb 865
6629161f 866 r = bus_message_parse_fields(m);
1307c3ff
LP
867 if (r < 0)
868 goto fail;
6629161f 869
9f97c936 870 /* Override information from the user header with data from the kernel */
51038c03 871 if (k->src_id == KDBUS_SRC_ID_KERNEL)
253ce82b 872 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
51038c03
LP
873 else {
874 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
49b832c5 875 m->sender = m->creds.unique_name = m->sender_buffer;
51038c03
LP
876 }
877
8e8d3760
LP
878 if (destination)
879 m->destination = destination;
880 else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
881 m->destination = NULL;
882 else if (k->dst_id == KDBUS_DST_ID_NAME)
883 m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
884 else {
885 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
886 m->destination = m->destination_buffer;
51038c03
LP
887 }
888
6629161f
LP
889 /* We take possession of the kmsg struct now */
890 m->kdbus = k;
fd8d62d9 891 m->release_kdbus = true;
6629161f 892 m->free_fds = true;
6629161f
LP
893 fds = NULL;
894
7adc46fc 895 bus->rqueue[bus->rqueue_size++] = m;
7d22c717 896
6629161f 897 return 1;
1307c3ff
LP
898
899fail:
900 if (m) {
901 struct bus_body_part *part;
902 unsigned i;
903
904 /* Make sure the memfds are not freed twice */
905 MESSAGE_FOREACH_PART(part, i, m)
906 if (part->memfd >= 0)
907 part->memfd = -1;
908
909 sd_bus_message_unref(m);
910 }
911
912 return r;
6629161f
LP
913}
914
7d22c717 915int bus_kernel_read_message(sd_bus *bus) {
6629161f 916 struct kdbus_msg *k;
7d22c717 917 uint64_t off;
6629161f
LP
918 int r;
919
920 assert(bus);
7d22c717 921
7adc46fc 922 r = bus_rqueue_make_room(bus);
7d22c717
LP
923 if (r < 0)
924 return r;
6629161f 925
62b3e928 926 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
fd8d62d9 927 if (r < 0) {
6629161f
LP
928 if (errno == EAGAIN)
929 return 0;
930
fd8d62d9 931 return -errno;
6629161f 932 }
62b3e928 933 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
6629161f 934
e1d337d4 935 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
7d22c717 936 r = bus_kernel_make_message(bus, k);
e1d337d4
LP
937
938 /* Anybody can send us invalid messages, let's just drop them. */
939 if (r == -EBADMSG || r == -EPROTOTYPE) {
ff4994c5 940 log_debug("Ignoring invalid message: %s", strerror(-r));
e1d337d4
LP
941 r = 0;
942 }
943
944 } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
7d22c717 945 r = bus_kernel_translate_message(bus, k);
777d7a61
LP
946 else
947 r = 0;
948
fd8d62d9
LP
949 if (r <= 0)
950 close_kdbus_msg(bus, k);
6629161f 951
51038c03 952 return r < 0 ? r : 1;
6629161f
LP
953}
954
8e959fbf 955int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
bc7fd8cd 956 struct memfd_cache *c;
45fbe937 957 int fd;
bc7fd8cd
LP
958
959 assert(address);
8e959fbf
LP
960 assert(mapped);
961 assert(allocated);
35460afc
LP
962
963 if (!bus || !bus->is_kernel)
964 return -ENOTSUP;
bc7fd8cd 965
76b7742c 966 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
45fbe937 967
bc7fd8cd 968 if (bus->n_memfd_cache <= 0) {
45fbe937
LP
969 int r;
970
76b7742c 971 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 972
9b05bc48
LP
973 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
974 if (r < 0)
bc7fd8cd
LP
975 return -errno;
976
977 *address = NULL;
8e959fbf
LP
978 *mapped = 0;
979 *allocated = 0;
bc7fd8cd
LP
980 return fd;
981 }
982
bf30e48f 983 c = &bus->memfd_cache[--bus->n_memfd_cache];
bc7fd8cd
LP
984
985 assert(c->fd >= 0);
8e959fbf 986 assert(c->mapped == 0 || c->address);
bc7fd8cd
LP
987
988 *address = c->address;
8e959fbf
LP
989 *mapped = c->mapped;
990 *allocated = c->allocated;
45fbe937
LP
991 fd = c->fd;
992
76b7742c 993 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 994
45fbe937
LP
995 return fd;
996}
997
998static void close_and_munmap(int fd, void *address, size_t size) {
999 if (size > 0)
76b7742c 1000 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
45fbe937
LP
1001
1002 close_nointr_nofail(fd);
bc7fd8cd
LP
1003}
1004
8e959fbf 1005void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
bc7fd8cd 1006 struct memfd_cache *c;
8e959fbf 1007 uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
bc7fd8cd
LP
1008
1009 assert(fd >= 0);
8e959fbf 1010 assert(mapped == 0 || address);
bc7fd8cd 1011
45fbe937 1012 if (!bus || !bus->is_kernel) {
8e959fbf 1013 close_and_munmap(fd, address, mapped);
45fbe937
LP
1014 return;
1015 }
1016
76b7742c 1017 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1018
45fbe937 1019 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
76b7742c 1020 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1021
8e959fbf 1022 close_and_munmap(fd, address, mapped);
bc7fd8cd
LP
1023 return;
1024 }
1025
1026 c = &bus->memfd_cache[bus->n_memfd_cache++];
1027 c->fd = fd;
1028 c->address = address;
1029
1030 /* If overly long, let's return a bit to the OS */
8e959fbf
LP
1031 if (mapped > max_mapped) {
1032 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_mapped) >= 0);
1033 assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
1034 c->mapped = c->allocated = max_mapped;
1035 } else {
1036 c->mapped = mapped;
1037 c->allocated = allocated;
1038 }
45fbe937 1039
76b7742c 1040 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd
LP
1041}
1042
1043void bus_kernel_flush_memfd(sd_bus *b) {
1044 unsigned i;
1045
1046 assert(b);
1047
76b7742c 1048 for (i = 0; i < b->n_memfd_cache; i++)
8e959fbf 1049 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
bc7fd8cd 1050}
0253ddcc 1051
e3dd987c
LP
1052int kdbus_translate_request_name_flags(uint64_t flags, uint64_t *kdbus_flags) {
1053 uint64_t f = 0;
0253ddcc 1054
e3dd987c 1055 assert(kdbus_flags);
0253ddcc 1056
e3dd987c
LP
1057 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1058 f |= KDBUS_NAME_ALLOW_REPLACEMENT;
0253ddcc 1059
e3dd987c
LP
1060 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
1061 f |= KDBUS_NAME_REPLACE_EXISTING;
0253ddcc 1062
d90bb669 1063 if (flags & SD_BUS_NAME_QUEUE)
e3dd987c 1064 f |= KDBUS_NAME_QUEUE;
0253ddcc 1065
e3dd987c
LP
1066 *kdbus_flags = f;
1067 return 0;
1068}
1069
1070int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
1071 uint64_t m = 0;
1072
1073 assert(kdbus_mask);
1074
1075 if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
1076 m |= KDBUS_ATTACH_CREDS;
1077
1078 if (mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM))
1079 m |= KDBUS_ATTACH_COMM;
1080
1081 if (mask & SD_BUS_CREDS_EXE)
1082 m |= KDBUS_ATTACH_EXE;
1083
1084 if (mask & SD_BUS_CREDS_CMDLINE)
1085 m |= KDBUS_ATTACH_CMDLINE;
1086
1087 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))
1088 m |= KDBUS_ATTACH_CGROUP;
1089
1090 if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
1091 m |= KDBUS_ATTACH_CAPS;
1092
1093 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
1094 m |= KDBUS_ATTACH_SECLABEL;
0253ddcc 1095
e3dd987c
LP
1096 if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
1097 m |= KDBUS_ATTACH_AUDIT;
1098
49b832c5
LP
1099 if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
1100 m |= KDBUS_ATTACH_NAMES;
1101
e3dd987c 1102 *kdbus_mask = m;
0253ddcc
DM
1103 return 0;
1104}
e3dd987c 1105
9bd37b40 1106int bus_kernel_create_bus(const char *name, char **s) {
816a3f9e 1107 struct kdbus_cmd_make *make;
e3dd987c
LP
1108 struct kdbus_item *n;
1109 int fd;
1110
1111 assert(name);
1112 assert(s);
1113
1114 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
1115 if (fd < 0)
1116 return -errno;
1117
816a3f9e
DM
1118 make = alloca0(ALIGN8(offsetof(struct kdbus_cmd_make, items) +
1119 offsetof(struct kdbus_item, data64) + sizeof(uint64_t) +
e3dd987c
LP
1120 offsetof(struct kdbus_item, str) +
1121 DECIMAL_STR_MAX(uid_t) + 1 + strlen(name) + 1));
1122
816a3f9e
DM
1123 make->size = offsetof(struct kdbus_cmd_make, items);
1124
e3dd987c 1125 n = make->items;
816a3f9e
DM
1126 n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
1127 n->type = KDBUS_ITEM_BLOOM_SIZE;
1128 n->data64[0] = BLOOM_SIZE;
1129 assert_cc(BLOOM_SIZE % 8 == 0);
1130 make->size += ALIGN8(n->size);
1131
1132 n = KDBUS_ITEM_NEXT(n);
e3dd987c
LP
1133 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
1134 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
5e16c257 1135 n->type = KDBUS_ITEM_MAKE_NAME;
816a3f9e 1136 make->size += ALIGN8(n->size);
e3dd987c 1137
e3dd987c 1138 make->flags = KDBUS_MAKE_POLICY_OPEN;
e3dd987c
LP
1139
1140 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
1141 close_nointr_nofail(fd);
1142 return -errno;
1143 }
1144
f9638db8
LP
1145 /* The higher 32bit of the flags field are considered
1146 * 'incompatible flags'. Refuse them all for now. */
1147 if (make->flags > 0xFFFFFFFFULL) {
1148 close_nointr_nofail(fd);
1149 return -ENOTSUP;
1150 }
1151
e3dd987c
LP
1152 if (s) {
1153 char *p;
1154
1155 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
1156 if (!p) {
1157 close_nointr_nofail(fd);
1158 return -ENOMEM;
1159 }
1160
1161 *s = p;
1162 }
1163
1164 return fd;
1165}
9bd37b40 1166
e821075a
LP
1167int bus_kernel_create_starter(const char *bus, const char *name) {
1168 struct kdbus_cmd_hello *hello;
1169 struct kdbus_item *n;
1170 char *p;
1171 int fd;
1172
1173 assert(bus);
1174 assert(name);
1175
1176 p = alloca(sizeof("/dev/kdbus/") - 1 + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + sizeof("/bus"));
1177 sprintf(p, "/dev/kdbus/%lu-%s/bus", (unsigned long) getuid(), bus);
1178
1179 fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
1180 if (fd < 0)
1181 return -errno;
1182
1183 hello = alloca0(ALIGN8(offsetof(struct kdbus_cmd_hello, items) +
1184 offsetof(struct kdbus_item, str) +
1185 strlen(name) + 1));
1186
1187 n = hello->items;
1188 strcpy(n->str, name);
1189 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
613ec4b8 1190 n->type = KDBUS_ITEM_NAME;
e821075a
LP
1191
1192 hello->size = ALIGN8(offsetof(struct kdbus_cmd_hello, items) + n->size);
07442eff 1193 hello->conn_flags = KDBUS_HELLO_ACTIVATOR;
e821075a
LP
1194 hello->pool_size = KDBUS_POOL_SIZE;
1195
1196 if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
1197 close_nointr_nofail(fd);
1198 return -errno;
1199 }
1200
1201 /* The higher 32bit of both flags fields are considered
1202 * 'incompatible flags'. Refuse them all for now. */
1203 if (hello->bus_flags > 0xFFFFFFFFULL ||
1204 hello->conn_flags > 0xFFFFFFFFULL) {
1205 close_nointr_nofail(fd);
1206 return -ENOTSUP;
1207 }
1208
1209 if (hello->bloom_size != BLOOM_SIZE) {
1210 close_nointr_nofail(fd);
1211 return -ENOTSUP;
1212 }
1213
1214 return fd;
1215}
1216
9bd37b40 1217int bus_kernel_create_namespace(const char *name, char **s) {
816a3f9e 1218 struct kdbus_cmd_make *make;
9bd37b40
LP
1219 struct kdbus_item *n;
1220 int fd;
1221
1222 assert(name);
1223 assert(s);
1224
1225 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
1226 if (fd < 0)
1227 return -errno;
1228
816a3f9e 1229 make = alloca0(ALIGN8(offsetof(struct kdbus_cmd_make, items) +
9bd37b40
LP
1230 offsetof(struct kdbus_item, str) +
1231 strlen(name) + 1));
1232
1233 n = make->items;
1234 strcpy(n->str, name);
1235 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
5e16c257 1236 n->type = KDBUS_ITEM_MAKE_NAME;
9bd37b40 1237
816a3f9e 1238 make->size = ALIGN8(offsetof(struct kdbus_cmd_make, items) + n->size);
fd5b0b91 1239 make->flags = KDBUS_MAKE_POLICY_OPEN | KDBUS_MAKE_ACCESS_WORLD;
9bd37b40
LP
1240
1241 if (ioctl(fd, KDBUS_CMD_NS_MAKE, make) < 0) {
1242 close_nointr_nofail(fd);
1243 return -errno;
1244 }
1245
f9638db8
LP
1246 /* The higher 32bit of the flags field are considered
1247 * 'incompatible flags'. Refuse them all for now. */
1248 if (make->flags > 0xFFFFFFFFULL) {
1249 close_nointr_nofail(fd);
1250 return -ENOTSUP;
1251 }
1252
9bd37b40
LP
1253 if (s) {
1254 char *p;
1255
f8a2d1c9 1256 p = strappend("/dev/kdbus/ns/", name);
9bd37b40
LP
1257 if (!p) {
1258 close_nointr_nofail(fd);
1259 return -ENOMEM;
1260 }
1261
1262 *s = p;
1263 }
1264
1265 return fd;
1266}
c8fa3f60 1267
b6c631f3
KS
1268int bus_kernel_create_monitor(const char *bus) {
1269 struct kdbus_cmd_hello *hello;
1270 char *p;
1271 int fd;
c8fa3f60
LS
1272
1273 assert(bus);
1274
b6c631f3
KS
1275 p = alloca(sizeof("/dev/kdbus/") - 1 + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + sizeof("/bus"));
1276 sprintf(p, "/dev/kdbus/%lu-%s/bus", (unsigned long) getuid(), bus);
c8fa3f60 1277
b6c631f3
KS
1278 fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
1279 if (fd < 0)
c8fa3f60
LS
1280 return -errno;
1281
b6c631f3
KS
1282 hello = alloca0(sizeof(struct kdbus_cmd_hello));
1283 hello->size = sizeof(struct kdbus_cmd_hello);
1284 hello->conn_flags = KDBUS_HELLO_ACTIVATOR;
1285 hello->pool_size = KDBUS_POOL_SIZE;
1286
1287 if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
1288 close_nointr_nofail(fd);
1289 return -errno;
1290 }
1291
1292 /* The higher 32bit of both flags fields are considered
1293 * 'incompatible flags'. Refuse them all for now. */
1294 if (hello->bus_flags > 0xFFFFFFFFULL ||
1295 hello->conn_flags > 0xFFFFFFFFULL) {
1296 close_nointr_nofail(fd);
1297 return -ENOTSUP;
1298 }
1299
1300 return fd;
c8fa3f60 1301}
ae095f86
LP
1302
1303int bus_kernel_try_close(sd_bus *bus) {
1304 assert(bus);
1305 assert(bus->is_kernel);
1306
1307 if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE) < 0)
1308 return -errno;
1309
1310 return 0;
1311}