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