]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-kernel.c
Revert "systemd: add a start job for all units in SYSTEMD_[USER_]WANTS="
[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) {
62b3e928 320 struct kdbus_cmd_hello hello;
6629161f
LP
321 int r;
322
323 assert(b);
f7e2bd5a 324 assert_return(!b->is_server, -EINVAL);
f08838da 325
8f155917
LP
326 b->use_memfd = 1;
327
62b3e928
KS
328 zero(hello);
329 hello.size = sizeof(hello);
330 hello.conn_flags = b->hello_flags;
d21a7bb1 331 hello.attach_flags = b->attach_flags;
62b3e928
KS
332 hello.pool_size = KDBUS_POOL_SIZE;
333
334 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
335 if (r < 0)
336 return -errno;
337
fd8d62d9 338 if (!b->kdbus_buffer) {
62b3e928 339 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
fd8d62d9
LP
340 if (b->kdbus_buffer == MAP_FAILED) {
341 b->kdbus_buffer = NULL;
342 return -errno;
343 }
344 }
345
5b7d4c1c
LP
346 /* The higher 32bit of both flags fields are considered
347 * 'incompatible flags'. Refuse them all for now. */
62b3e928
KS
348 if (hello.bus_flags > 0xFFFFFFFFULL ||
349 hello.conn_flags > 0xFFFFFFFFULL)
5b7d4c1c
LP
350 return -ENOTSUP;
351
62b3e928 352 if (hello.bloom_size != BLOOM_SIZE)
a56f19c4
LP
353 return -ENOTSUP;
354
62b3e928 355 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
de297575
LP
356 return -ENOMEM;
357
219728b3
LP
358 b->unique_id = hello.id;
359
6629161f 360 b->is_kernel = true;
f08838da 361 b->bus_client = true;
62b3e928 362 b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
e1d337d4 363 b->message_version = 2;
6629161f 364
c58dea19
DM
365 /* the kernel told us the UUID of the underlying bus */
366 memcpy(b->server_id.bytes, hello.id128, sizeof(b->server_id.bytes));
367
7adc46fc 368 return bus_start_running(b);
6629161f
LP
369}
370
371int bus_kernel_connect(sd_bus *b) {
372 assert(b);
373 assert(b->input_fd < 0);
374 assert(b->output_fd < 0);
375 assert(b->kernel);
f7e2bd5a 376 assert_return(!b->is_server, -EINVAL);
f08838da 377
6629161f 378 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
c320885c 379 if (b->input_fd < 0)
6629161f
LP
380 return -errno;
381
382 b->output_fd = b->input_fd;
383
384 return bus_kernel_take_fd(b);
385}
386
387int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
388 int r;
389
390 assert(bus);
391 assert(m);
392 assert(bus->state == BUS_RUNNING);
393
a43b9ca3
LP
394 /* If we can't deliver, we want room for the error message */
395 r = bus_rqueue_make_room(bus);
396 if (r < 0)
397 return r;
398
5b7d4c1c 399 r = bus_message_setup_kmsg(bus, m);
6629161f
LP
400 if (r < 0)
401 return r;
402
403 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
a43b9ca3
LP
404 if (r < 0) {
405 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
406 sd_bus_message *reply;
407
408 if (errno == EAGAIN || errno == EINTR)
409 return 0;
410 else if (errno == ENXIO || errno == ESRCH) {
411
412 /* ENXIO: unique name not known
413 * ESRCH: well-known name not known */
414
415 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
416 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
417 else
418 return 0;
419
420 } else if (errno == EADDRNOTAVAIL) {
421
422 /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
423
424 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
425 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
426 else
427 return 0;
428 } else
429 return -errno;
430
431 r = bus_message_new_synthetic_error(
432 bus,
433 BUS_MESSAGE_SERIAL(m),
434 &error,
435 &reply);
436
437 if (r < 0)
438 return r;
439
440 r = bus_seal_synthetic_message(bus, reply);
441 if (r < 0)
442 return r;
443
444 bus->rqueue[bus->rqueue_size++] = reply;
445
446 return 0;
447 }
6629161f 448
51038c03 449 return 1;
6629161f
LP
450}
451
fd8d62d9 452static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
62b3e928 453 uint64_t off;
febfd508 454 struct kdbus_item *d;
6629161f 455
fd8d62d9
LP
456 assert(bus);
457 assert(k);
458
62b3e928 459 off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
1d0e3c98 460 ioctl(bus->input_fd, KDBUS_CMD_FREE, &off);
fd8d62d9 461
a8d4cac5 462 KDBUS_ITEM_FOREACH(d, k, items) {
6629161f 463
ea1edece 464 if (d->type == KDBUS_ITEM_FDS)
1307c3ff 465 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
ea1edece 466 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
1307c3ff 467 close_nointr_nofail(d->memfd.fd);
6629161f
LP
468 }
469}
470
7d22c717 471static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) {
777d7a61
LP
472 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
473 int r;
474
475 assert(bus);
777d7a61
LP
476
477 r = sd_bus_message_new_signal(
478 bus,
479 "/org/freedesktop/DBus",
480 "org.freedesktop.DBus",
481 "NameOwnerChanged",
482 &m);
483 if (r < 0)
484 return r;
485
486 r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
487 if (r < 0)
488 return r;
489
490 m->sender = "org.freedesktop.DBus";
491
7adc46fc 492 r = bus_seal_synthetic_message(bus, m);
7d22c717
LP
493 if (r < 0)
494 return r;
777d7a61 495
7adc46fc 496 bus->rqueue[bus->rqueue_size++] = m;
7d22c717 497 m = NULL;
219728b3 498
219728b3
LP
499 return 1;
500}
501
7d22c717 502static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
777d7a61
LP
503 char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
504
505 assert(bus);
506 assert(k);
507 assert(d);
777d7a61
LP
508
509 if (d->name_change.flags != 0)
510 return 0;
511
512 if (d->type == KDBUS_ITEM_NAME_ADD)
513 old_owner[0] = 0;
514 else
515 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id);
516
517 if (d->type == KDBUS_ITEM_NAME_REMOVE)
518 new_owner[0] = 0;
519 else
520 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id);
521
7d22c717 522 return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner);
777d7a61
LP
523}
524
7d22c717 525static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
777d7a61
LP
526 char owner[UNIQUE_NAME_MAX];
527
528 assert(bus);
529 assert(k);
530 assert(d);
777d7a61
LP
531
532 sprintf(owner, ":1.%llu", d->id_change.id);
533
7d22c717 534 return push_name_owner_changed(
777d7a61
LP
535 bus, owner,
536 d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
7d22c717 537 d->type == KDBUS_ITEM_ID_ADD ? owner : NULL);
777d7a61
LP
538}
539
7d22c717 540static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
777d7a61
LP
541 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
542 int r;
543
544 assert(bus);
545 assert(k);
546 assert(d);
777d7a61
LP
547
548 r = bus_message_new_synthetic_error(
549 bus,
550 k->cookie_reply,
551 d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
552 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
553 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
554 &m);
555 if (r < 0)
556 return r;
557
558 m->sender = "org.freedesktop.DBus";
559
7adc46fc 560 r = bus_seal_synthetic_message(bus, m);
7d22c717
LP
561 if (r < 0)
562 return r;
777d7a61 563
7adc46fc 564 bus->rqueue[bus->rqueue_size++] = m;
7d22c717 565 m = NULL;
7adc46fc 566
777d7a61
LP
567 return 1;
568}
569
7d22c717 570static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
777d7a61
LP
571 struct kdbus_item *d, *found = NULL;
572
7d22c717 573 static int (* const translate[])(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) = {
777d7a61
LP
574 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
575 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
576 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
577
578 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
579 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
580
581 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
582 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
583 };
584
585 assert(bus);
586 assert(k);
777d7a61
LP
587 assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
588
a8d4cac5 589 KDBUS_ITEM_FOREACH(d, k, items) {
777d7a61
LP
590 if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
591 if (found)
592 return -EBADMSG;
593 found = d;
594 } else
595 log_debug("Got unknown field from kernel %llu", d->type);
596 }
597
598 if (!found) {
599 log_debug("Didn't find a kernel message to translate.");
600 return 0;
601 }
602
51502af3 603 return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found);
777d7a61
LP
604}
605
7d22c717 606static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
6629161f 607 sd_bus_message *m = NULL;
febfd508 608 struct kdbus_item *d;
1307c3ff 609 unsigned n_fds = 0;
6629161f
LP
610 _cleanup_free_ int *fds = NULL;
611 struct bus_header *h = NULL;
612 size_t total, n_bytes = 0, idx = 0;
69aec65c 613 const char *destination = NULL, *seclabel = NULL;
6629161f
LP
614 int r;
615
616 assert(bus);
617 assert(k);
6647dc66 618 assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
6629161f 619
a8d4cac5 620 KDBUS_ITEM_FOREACH(d, k, items) {
6629161f
LP
621 size_t l;
622
febfd508 623 l = d->size - offsetof(struct kdbus_item, data);
6629161f 624
777d7a61 625 switch (d->type) {
6629161f 626
777d7a61 627 case KDBUS_ITEM_PAYLOAD_OFF:
6629161f 628 if (!h) {
62b3e928 629 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
c91cb83c
LP
630
631 if (!bus_header_is_complete(h, d->vec.size))
632 return -EBADMSG;
6629161f
LP
633 }
634
fd8d62d9 635 n_bytes += d->vec.size;
777d7a61 636 break;
6629161f 637
777d7a61 638 case KDBUS_ITEM_PAYLOAD_MEMFD:
1307c3ff
LP
639 if (!h)
640 return -EBADMSG;
641
642 n_bytes += d->memfd.size;
777d7a61 643 break;
1307c3ff 644
777d7a61 645 case KDBUS_ITEM_FDS: {
6629161f
LP
646 int *f;
647 unsigned j;
648
649 j = l / sizeof(int);
650 f = realloc(fds, sizeof(int) * (n_fds + j));
651 if (!f)
652 return -ENOMEM;
653
654 fds = f;
9097fe29 655 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
6629161f 656 n_fds += j;
777d7a61
LP
657 break;
658 }
f9be01f3 659
777d7a61 660 case KDBUS_ITEM_SECLABEL:
69aec65c 661 seclabel = d->str;
777d7a61
LP
662 break;
663 }
6629161f
LP
664 }
665
666 if (!h)
667 return -EBADMSG;
668
c91cb83c 669 r = bus_header_message_size(h, &total);
6629161f
LP
670 if (r < 0)
671 return r;
672
673 if (n_bytes != total)
674 return -EBADMSG;
675
e1d337d4
LP
676 /* on kdbus we only speak native endian gvariant, never dbus1
677 * marshalling or reverse endian */
678 if (h->version != 2 ||
679 h->endian != BUS_NATIVE_ENDIAN)
680 return -EPROTOTYPE;
681
df2d202e 682 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
6629161f
LP
683 if (r < 0)
684 return r;
685
a8d4cac5 686 KDBUS_ITEM_FOREACH(d, k, items) {
6629161f
LP
687 size_t l;
688
febfd508 689 l = d->size - offsetof(struct kdbus_item, data);
6629161f 690
777d7a61
LP
691 switch (d->type) {
692
693 case KDBUS_ITEM_PAYLOAD_OFF: {
bc7fd8cd 694 size_t begin_body;
fd8d62d9 695
c91cb83c 696 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
bc7fd8cd
LP
697
698 if (idx + d->vec.size > begin_body) {
699 struct bus_body_part *part;
700
701 /* Contains body material */
702
703 part = message_append_part(m);
704 if (!part) {
1307c3ff
LP
705 r = -ENOMEM;
706 goto fail;
bc7fd8cd
LP
707 }
708
62b3e928
KS
709 /* A -1 offset is NUL padding. */
710 part->is_zero = d->vec.offset == ~0ULL;
711
bc7fd8cd 712 if (idx >= begin_body) {
62b3e928
KS
713 if (!part->is_zero)
714 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
bc7fd8cd
LP
715 part->size = d->vec.size;
716 } else {
62b3e928
KS
717 if (!part->is_zero)
718 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
bc7fd8cd
LP
719 part->size = d->vec.size - (begin_body - idx);
720 }
721
722 part->sealed = true;
723 }
fd8d62d9
LP
724
725 idx += d->vec.size;
777d7a61
LP
726 break;
727 }
728
729 case KDBUS_ITEM_PAYLOAD_MEMFD: {
1307c3ff
LP
730 struct bus_body_part *part;
731
732 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
733 r = -EBADMSG;
734 goto fail;
735 }
736
737 part = message_append_part(m);
738 if (!part) {
739 r = -ENOMEM;
740 goto fail;
741 }
742
743 part->memfd = d->memfd.fd;
744 part->size = d->memfd.size;
745 part->sealed = true;
746
747 idx += d->memfd.size;
777d7a61
LP
748 break;
749 }
69aec65c 750
777d7a61 751 case KDBUS_ITEM_CREDS:
5b12334d
LP
752 m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
753 m->creds.uid = d->creds.uid;
754 m->creds.gid = d->creds.gid;
755 m->creds.pid = d->creds.pid;
756 m->creds.tid = d->creds.tid;
757 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 758 break;
5b12334d 759
777d7a61 760 case KDBUS_ITEM_TIMESTAMP:
69aec65c
LP
761 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
762 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
777d7a61 763 break;
5b12334d 764
777d7a61 765 case KDBUS_ITEM_PID_COMM:
5b12334d
LP
766 m->creds.comm = d->str;
767 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
777d7a61 768 break;
5b12334d 769
777d7a61 770 case KDBUS_ITEM_TID_COMM:
5b12334d
LP
771 m->creds.tid_comm = d->str;
772 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
777d7a61 773 break;
5b12334d 774
777d7a61 775 case KDBUS_ITEM_EXE:
5b12334d
LP
776 m->creds.exe = d->str;
777 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
777d7a61 778 break;
5b12334d 779
777d7a61 780 case KDBUS_ITEM_CMDLINE:
5b12334d 781 m->creds.cmdline = d->str;
49b832c5 782 m->creds.cmdline_size = l;
5b12334d 783 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
777d7a61 784 break;
5b12334d 785
777d7a61 786 case KDBUS_ITEM_CGROUP:
5b12334d
LP
787 m->creds.cgroup = d->str;
788 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 789 break;
5b12334d 790
777d7a61 791 case KDBUS_ITEM_AUDIT:
5b12334d
LP
792 m->creds.audit_session_id = d->audit.sessionid;
793 m->creds.audit_login_uid = d->audit.loginuid;
794 m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
777d7a61 795 break;
5b12334d 796
777d7a61 797 case KDBUS_ITEM_CAPS:
5b12334d
LP
798 m->creds.capability = d->data;
799 m->creds.capability_size = l;
800 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 801 break;
5b12334d 802
777d7a61 803 case KDBUS_ITEM_DST_NAME:
1307c3ff 804 destination = d->str;
777d7a61
LP
805 break;
806
65dae17a
KS
807 case KDBUS_ITEM_NAME:
808 r = strv_extend(&m->creds.well_known_names, d->name.name);
809 if (r < 0)
810 goto fail;
49b832c5
LP
811 m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES & bus->creds_mask;
812 break;
813
777d7a61
LP
814 case KDBUS_ITEM_FDS:
815 case KDBUS_ITEM_SECLABEL:
777d7a61
LP
816 break;
817
818 default:
77930f11 819 log_debug("Got unknown field from kernel %llu", d->type);
777d7a61 820 }
69aec65c 821 }
acb5a3cb 822
6629161f 823 r = bus_message_parse_fields(m);
1307c3ff
LP
824 if (r < 0)
825 goto fail;
6629161f 826
51038c03
LP
827 if (k->src_id == KDBUS_SRC_ID_KERNEL)
828 m->sender = "org.freedesktop.DBus";
829 else {
830 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
49b832c5
LP
831 m->sender = m->creds.unique_name = m->sender_buffer;
832 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & bus->creds_mask;
51038c03
LP
833 }
834
835 if (!m->destination) {
836 if (destination)
837 m->destination = destination;
144e9e58 838 else if (k->dst_id != KDBUS_DST_ID_NAME &&
51038c03
LP
839 k->dst_id != KDBUS_DST_ID_BROADCAST) {
840 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
841 m->destination = m->destination_buffer;
842 }
843 }
844
6629161f
LP
845 /* We take possession of the kmsg struct now */
846 m->kdbus = k;
fd8d62d9 847 m->release_kdbus = true;
6629161f 848 m->free_fds = true;
6629161f
LP
849 fds = NULL;
850
7adc46fc 851 bus->rqueue[bus->rqueue_size++] = m;
7d22c717 852
6629161f 853 return 1;
1307c3ff
LP
854
855fail:
856 if (m) {
857 struct bus_body_part *part;
858 unsigned i;
859
860 /* Make sure the memfds are not freed twice */
861 MESSAGE_FOREACH_PART(part, i, m)
862 if (part->memfd >= 0)
863 part->memfd = -1;
864
865 sd_bus_message_unref(m);
866 }
867
868 return r;
6629161f
LP
869}
870
7d22c717 871int bus_kernel_read_message(sd_bus *bus) {
6629161f 872 struct kdbus_msg *k;
7d22c717 873 uint64_t off;
6629161f
LP
874 int r;
875
876 assert(bus);
7d22c717 877
7adc46fc 878 r = bus_rqueue_make_room(bus);
7d22c717
LP
879 if (r < 0)
880 return r;
6629161f 881
62b3e928 882 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
fd8d62d9 883 if (r < 0) {
6629161f
LP
884 if (errno == EAGAIN)
885 return 0;
886
fd8d62d9 887 return -errno;
6629161f 888 }
62b3e928 889 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
6629161f 890
e1d337d4 891 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
7d22c717 892 r = bus_kernel_make_message(bus, k);
e1d337d4
LP
893
894 /* Anybody can send us invalid messages, let's just drop them. */
895 if (r == -EBADMSG || r == -EPROTOTYPE) {
896 log_error("Ignoring invalid message: %s", strerror(-r));
897 r = 0;
898 }
899
900 } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
7d22c717 901 r = bus_kernel_translate_message(bus, k);
777d7a61
LP
902 else
903 r = 0;
904
fd8d62d9
LP
905 if (r <= 0)
906 close_kdbus_msg(bus, k);
6629161f 907
51038c03 908 return r < 0 ? r : 1;
6629161f
LP
909}
910
bc7fd8cd
LP
911int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
912 struct memfd_cache *c;
45fbe937 913 int fd;
bc7fd8cd
LP
914
915 assert(address);
916 assert(size);
f7e2bd5a 917 assert_return(bus && bus->is_kernel, -ENOTSUP);
bc7fd8cd 918
76b7742c 919 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
45fbe937 920
bc7fd8cd 921 if (bus->n_memfd_cache <= 0) {
45fbe937
LP
922 int r;
923
76b7742c 924 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 925
9b05bc48
LP
926 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
927 if (r < 0)
bc7fd8cd
LP
928 return -errno;
929
930 *address = NULL;
931 *size = 0;
932 return fd;
933 }
934
bf30e48f 935 c = &bus->memfd_cache[--bus->n_memfd_cache];
bc7fd8cd
LP
936
937 assert(c->fd >= 0);
938 assert(c->size == 0 || c->address);
939
940 *address = c->address;
941 *size = c->size;
45fbe937
LP
942 fd = c->fd;
943
76b7742c 944 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 945
45fbe937
LP
946 return fd;
947}
948
949static void close_and_munmap(int fd, void *address, size_t size) {
950 if (size > 0)
76b7742c 951 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
45fbe937
LP
952
953 close_nointr_nofail(fd);
bc7fd8cd
LP
954}
955
956void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
957 struct memfd_cache *c;
76b7742c 958 uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
bc7fd8cd
LP
959
960 assert(fd >= 0);
961 assert(size == 0 || address);
962
45fbe937
LP
963 if (!bus || !bus->is_kernel) {
964 close_and_munmap(fd, address, size);
965 return;
966 }
967
76b7742c 968 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 969
45fbe937 970 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
76b7742c 971 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 972
45fbe937 973 close_and_munmap(fd, address, size);
bc7fd8cd
LP
974 return;
975 }
976
977 c = &bus->memfd_cache[bus->n_memfd_cache++];
978 c->fd = fd;
979 c->address = address;
980
981 /* If overly long, let's return a bit to the OS */
76b7742c
LP
982 if (size > max_sz) {
983 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
984 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
985 c->size = max_sz;
bc7fd8cd
LP
986 } else
987 c->size = size;
45fbe937 988
76b7742c 989 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd
LP
990}
991
992void bus_kernel_flush_memfd(sd_bus *b) {
993 unsigned i;
994
995 assert(b);
996
76b7742c
LP
997 for (i = 0; i < b->n_memfd_cache; i++)
998 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
bc7fd8cd 999}
0253ddcc 1000
e3dd987c
LP
1001int kdbus_translate_request_name_flags(uint64_t flags, uint64_t *kdbus_flags) {
1002 uint64_t f = 0;
0253ddcc 1003
e3dd987c 1004 assert(kdbus_flags);
0253ddcc 1005
e3dd987c
LP
1006 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1007 f |= KDBUS_NAME_ALLOW_REPLACEMENT;
0253ddcc 1008
e3dd987c
LP
1009 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
1010 f |= KDBUS_NAME_REPLACE_EXISTING;
0253ddcc 1011
e3dd987c
LP
1012 if (!(flags & SD_BUS_NAME_DO_NOT_QUEUE))
1013 f |= KDBUS_NAME_QUEUE;
0253ddcc 1014
e3dd987c
LP
1015 *kdbus_flags = f;
1016 return 0;
1017}
1018
1019int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
1020 uint64_t m = 0;
1021
1022 assert(kdbus_mask);
1023
1024 if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
1025 m |= KDBUS_ATTACH_CREDS;
1026
1027 if (mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM))
1028 m |= KDBUS_ATTACH_COMM;
1029
1030 if (mask & SD_BUS_CREDS_EXE)
1031 m |= KDBUS_ATTACH_EXE;
1032
1033 if (mask & SD_BUS_CREDS_CMDLINE)
1034 m |= KDBUS_ATTACH_CMDLINE;
1035
1036 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))
1037 m |= KDBUS_ATTACH_CGROUP;
1038
1039 if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
1040 m |= KDBUS_ATTACH_CAPS;
1041
1042 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
1043 m |= KDBUS_ATTACH_SECLABEL;
0253ddcc 1044
e3dd987c
LP
1045 if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
1046 m |= KDBUS_ATTACH_AUDIT;
1047
49b832c5
LP
1048 if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
1049 m |= KDBUS_ATTACH_NAMES;
1050
e3dd987c 1051 *kdbus_mask = m;
0253ddcc
DM
1052 return 0;
1053}
e3dd987c 1054
9bd37b40 1055int bus_kernel_create_bus(const char *name, char **s) {
e3dd987c
LP
1056 struct kdbus_cmd_bus_make *make;
1057 struct kdbus_item *n;
1058 int fd;
1059
1060 assert(name);
1061 assert(s);
1062
1063 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
1064 if (fd < 0)
1065 return -errno;
1066
1067 make = alloca0(ALIGN8(offsetof(struct kdbus_cmd_bus_make, items) +
1068 offsetof(struct kdbus_item, str) +
1069 DECIMAL_STR_MAX(uid_t) + 1 + strlen(name) + 1));
1070
1071 n = make->items;
1072 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
1073 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
5e16c257 1074 n->type = KDBUS_ITEM_MAKE_NAME;
e3dd987c
LP
1075
1076 make->size = ALIGN8(offsetof(struct kdbus_cmd_bus_make, items) + n->size);
1077 make->flags = KDBUS_MAKE_POLICY_OPEN;
e3dd987c
LP
1078 make->bloom_size = BLOOM_SIZE;
1079 assert_cc(BLOOM_SIZE % 8 == 0);
1080
1081 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
1082 close_nointr_nofail(fd);
1083 return -errno;
1084 }
1085
f9638db8
LP
1086 /* The higher 32bit of the flags field are considered
1087 * 'incompatible flags'. Refuse them all for now. */
1088 if (make->flags > 0xFFFFFFFFULL) {
1089 close_nointr_nofail(fd);
1090 return -ENOTSUP;
1091 }
1092
e3dd987c
LP
1093 if (s) {
1094 char *p;
1095
1096 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
1097 if (!p) {
1098 close_nointr_nofail(fd);
1099 return -ENOMEM;
1100 }
1101
1102 *s = p;
1103 }
1104
1105 return fd;
1106}
9bd37b40 1107
e821075a
LP
1108int bus_kernel_create_starter(const char *bus, const char *name) {
1109 struct kdbus_cmd_hello *hello;
1110 struct kdbus_item *n;
1111 char *p;
1112 int fd;
1113
1114 assert(bus);
1115 assert(name);
1116
1117 p = alloca(sizeof("/dev/kdbus/") - 1 + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + sizeof("/bus"));
1118 sprintf(p, "/dev/kdbus/%lu-%s/bus", (unsigned long) getuid(), bus);
1119
1120 fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
1121 if (fd < 0)
1122 return -errno;
1123
1124 hello = alloca0(ALIGN8(offsetof(struct kdbus_cmd_hello, items) +
1125 offsetof(struct kdbus_item, str) +
1126 strlen(name) + 1));
1127
1128 n = hello->items;
1129 strcpy(n->str, name);
1130 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
1131 n->type = KDBUS_ITEM_STARTER_NAME;
1132
1133 hello->size = ALIGN8(offsetof(struct kdbus_cmd_hello, items) + n->size);
1134 hello->conn_flags = KDBUS_HELLO_STARTER;
1135 hello->pool_size = KDBUS_POOL_SIZE;
1136
1137 if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
1138 close_nointr_nofail(fd);
1139 return -errno;
1140 }
1141
1142 /* The higher 32bit of both flags fields are considered
1143 * 'incompatible flags'. Refuse them all for now. */
1144 if (hello->bus_flags > 0xFFFFFFFFULL ||
1145 hello->conn_flags > 0xFFFFFFFFULL) {
1146 close_nointr_nofail(fd);
1147 return -ENOTSUP;
1148 }
1149
1150 if (hello->bloom_size != BLOOM_SIZE) {
1151 close_nointr_nofail(fd);
1152 return -ENOTSUP;
1153 }
1154
1155 return fd;
1156}
1157
9bd37b40
LP
1158int bus_kernel_create_namespace(const char *name, char **s) {
1159 struct kdbus_cmd_ns_make *make;
1160 struct kdbus_item *n;
1161 int fd;
1162
1163 assert(name);
1164 assert(s);
1165
1166 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
1167 if (fd < 0)
1168 return -errno;
1169
1170 make = alloca0(ALIGN8(offsetof(struct kdbus_cmd_ns_make, items) +
1171 offsetof(struct kdbus_item, str) +
1172 strlen(name) + 1));
1173
1174 n = make->items;
1175 strcpy(n->str, name);
1176 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
5e16c257 1177 n->type = KDBUS_ITEM_MAKE_NAME;
9bd37b40
LP
1178
1179 make->size = ALIGN8(offsetof(struct kdbus_cmd_ns_make, items) + n->size);
fd5b0b91 1180 make->flags = KDBUS_MAKE_POLICY_OPEN | KDBUS_MAKE_ACCESS_WORLD;
9bd37b40
LP
1181
1182 if (ioctl(fd, KDBUS_CMD_NS_MAKE, make) < 0) {
1183 close_nointr_nofail(fd);
1184 return -errno;
1185 }
1186
f9638db8
LP
1187 /* The higher 32bit of the flags field are considered
1188 * 'incompatible flags'. Refuse them all for now. */
1189 if (make->flags > 0xFFFFFFFFULL) {
1190 close_nointr_nofail(fd);
1191 return -ENOTSUP;
1192 }
1193
9bd37b40
LP
1194 if (s) {
1195 char *p;
1196
f8a2d1c9 1197 p = strappend("/dev/kdbus/ns/", name);
9bd37b40
LP
1198 if (!p) {
1199 close_nointr_nofail(fd);
1200 return -ENOMEM;
1201 }
1202
1203 *s = p;
1204 }
1205
1206 return fd;
1207}