]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-kernel.c
systemd-python: do not attempt to convert str to bytes
[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"
31
32#include "bus-internal.h"
33#include "bus-message.h"
34#include "bus-kernel.h"
a56f19c4 35#include "bus-bloom.h"
6629161f 36
6133cee2
KS
37#define KDBUS_ITEM_NEXT(item) \
38 (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
9097fe29 39
6133cee2
KS
40#define KDBUS_ITEM_FOREACH(item, head) \
41 for (item = (head)->items; \
42 (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \
43 item = KDBUS_ITEM_NEXT(item))
6629161f 44
febfd508
KS
45#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
46#define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
47
13019ef5 48#define KDBUS_POOL_SIZE (4*1024*1024)
fd8d62d9 49
6629161f
LP
50static int parse_unique_name(const char *s, uint64_t *id) {
51 int r;
52
53 assert(s);
54 assert(id);
55
56 if (!startswith(s, ":1."))
57 return 0;
58
59 r = safe_atou64(s + 3, id);
60 if (r < 0)
61 return r;
62
63 return 1;
64}
65
febfd508 66static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
6629161f 67 assert(d);
6629161f
LP
68 assert(sz > 0);
69
e86b80b8
LP
70 *d = ALIGN8_PTR(*d);
71
febfd508 72 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
6629161f 73 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
a392d361 74 (*d)->vec.address = PTR_TO_UINT64(p);
6629161f
LP
75 (*d)->vec.size = sz;
76
febfd508 77 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
6629161f
LP
78}
79
a392d361
LP
80static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
81 assert(d);
82 assert(memfd >= 0);
83 assert(sz > 0);
84
85 *d = ALIGN8_PTR(*d);
86 (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
87 (*d)->type = KDBUS_MSG_PAYLOAD_MEMFD;
88 (*d)->memfd.fd = memfd;
89 (*d)->memfd.size = sz;
90
91 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
92}
93
febfd508 94static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
6629161f 95 assert(d);
b5baa8fe 96 assert(s);
6629161f 97
e86b80b8
LP
98 *d = ALIGN8_PTR(*d);
99
febfd508 100 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
6629161f 101 (*d)->type = KDBUS_MSG_DST_NAME;
51038c03 102 memcpy((*d)->str, s, length + 1);
6629161f 103
febfd508 104 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
6629161f
LP
105}
106
febfd508 107static void* append_bloom(struct kdbus_item **d, size_t length) {
a56f19c4
LP
108 void *r;
109
b5baa8fe 110 assert(d);
b5baa8fe
LP
111
112 *d = ALIGN8_PTR(*d);
113
febfd508 114 (*d)->size = offsetof(struct kdbus_item, data) + length;
b5baa8fe 115 (*d)->type = KDBUS_MSG_BLOOM;
a56f19c4 116 r = (*d)->data;
b5baa8fe 117
febfd508 118 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
a56f19c4
LP
119
120 return r;
121}
122
febfd508 123static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
9097fe29
LP
124 assert(d);
125 assert(fds);
126 assert(n_fds > 0);
127
128 *d = ALIGN8_PTR(*d);
febfd508 129 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
fd8d62d9 130 (*d)->type = KDBUS_MSG_FDS;
9097fe29
LP
131 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
132
febfd508 133 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
9097fe29
LP
134}
135
a56f19c4
LP
136static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
137 unsigned i;
138 int r;
139
140 assert(m);
141 assert(bloom);
142
143 memset(bloom, 0, BLOOM_SIZE);
144
145 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
146
147 if (m->interface)
148 bloom_add_pair(bloom, "interface", m->interface);
149 if (m->member)
150 bloom_add_pair(bloom, "member", m->member);
151 if (m->path) {
152 bloom_add_pair(bloom, "path", m->path);
153 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
154 }
155
156 r = sd_bus_message_rewind(m, true);
157 if (r < 0)
158 return r;
159
160 for (i = 0; i < 64; i++) {
161 char type;
162 const char *t;
163 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
164 char *e;
165
166 r = sd_bus_message_peek_type(m, &type, NULL);
167 if (r < 0)
168 return r;
169
170 if (type != SD_BUS_TYPE_STRING &&
171 type != SD_BUS_TYPE_OBJECT_PATH &&
172 type != SD_BUS_TYPE_SIGNATURE)
173 break;
174
175 r = sd_bus_message_read_basic(m, type, &t);
176 if (r < 0)
177 return r;
178
179 e = stpcpy(buf, "arg");
180 if (i < 10)
181 *(e++) = '0' + i;
182 else {
183 *(e++) = '0' + (i / 10);
184 *(e++) = '0' + (i % 10);
185 }
186
187 *e = 0;
188 bloom_add_pair(bloom, buf, t);
189
190 strcpy(e, "-dot-prefix");
191 bloom_add_prefixes(bloom, buf, t, '.');
192 strcpy(e, "-slash-prefix");
193 bloom_add_prefixes(bloom, buf, t, '/');
194 }
195
196 return 0;
b5baa8fe
LP
197}
198
5b7d4c1c 199static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
9b29bb68 200 struct bus_body_part *part;
febfd508 201 struct kdbus_item *d;
6629161f
LP
202 bool well_known;
203 uint64_t unique;
204 size_t sz, dl;
9b29bb68 205 unsigned i;
6629161f
LP
206 int r;
207
5b7d4c1c 208 assert(b);
6629161f
LP
209 assert(m);
210 assert(m->sealed);
e9a967f9
LP
211
212 if (m->kdbus)
213 return 0;
6629161f
LP
214
215 if (m->destination) {
216 r = parse_unique_name(m->destination, &unique);
217 if (r < 0)
218 return r;
219
220 well_known = r == 0;
221 } else
222 well_known = false;
223
b1454bf0 224 sz = offsetof(struct kdbus_msg, items);
6629161f 225
a392d361
LP
226 assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
227 ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
228
69aec65c 229 /* Add in fixed header, fields header and payload */
c91cb83c 230 sz += (1 + m->n_body_parts) *
bc7fd8cd 231 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
6629161f 232
69aec65c 233 /* Add space for bloom filter */
febfd508 234 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
b5baa8fe 235
6629161f
LP
236 /* Add in well-known destination header */
237 if (well_known) {
238 dl = strlen(m->destination);
febfd508 239 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
6629161f
LP
240 }
241
9097fe29
LP
242 /* Add space for unix fds */
243 if (m->n_fds > 0)
febfd508 244 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
9097fe29 245
c556fe79 246 m->kdbus = memalign(8, sz);
6629161f
LP
247 if (!m->kdbus)
248 return -ENOMEM;
249
d9115e18
LP
250 memset(m->kdbus, 0, sz);
251
6629161f
LP
252 m->kdbus->flags =
253 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
254 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
255 m->kdbus->dst_id =
256 well_known ? 0 :
b5baa8fe 257 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
6629161f
LP
258 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
259 m->kdbus->cookie = m->header->serial;
260
261 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
262
b1454bf0 263 d = m->kdbus->items;
6629161f
LP
264
265 if (well_known)
266 append_destination(&d, m->destination, dl);
267
c91cb83c 268 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
a392d361
LP
269
270 MESSAGE_FOREACH_PART(part, i, m) {
271 if (part->is_zero) {
272 append_payload_vec(&d, NULL, part->size);
273 continue;
274 }
275
276 if (part->memfd >= 0 && part->sealed) {
277 bus_body_part_unmap(part);
278
279 if (!part->data) {
280 append_payload_memfd(&d, part->memfd, part->size);
281 continue;
282 }
283 }
284
285 if (part->memfd >= 0) {
286 r = bus_body_part_map(part);
287 if (r < 0)
288 goto fail;
289 }
290
bc7fd8cd 291 append_payload_vec(&d, part->data, part->size);
a392d361 292 }
6629161f 293
5b7d4c1c
LP
294 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
295 void *p;
296
a56f19c4
LP
297 p = append_bloom(&d, BLOOM_SIZE);
298 r = bus_message_setup_bloom(m, p);
a392d361
LP
299 if (r < 0)
300 goto fail;
5b7d4c1c 301 }
b5baa8fe 302
9097fe29
LP
303 if (m->n_fds > 0)
304 append_fds(&d, m->fds, m->n_fds);
305
e9a967f9 306 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
6629161f
LP
307 assert(m->kdbus->size <= sz);
308
e9a967f9
LP
309 m->free_kdbus = true;
310
6629161f 311 return 0;
a392d361
LP
312
313fail:
314 free(m->kdbus);
315 m->kdbus = NULL;
316 return r;
6629161f
LP
317}
318
319int bus_kernel_take_fd(sd_bus *b) {
fd8d62d9
LP
320 uint8_t h[ALIGN8(sizeof(struct kdbus_cmd_hello)) +
321 ALIGN8(KDBUS_ITEM_HEADER_SIZE) +
322 ALIGN8(sizeof(struct kdbus_vec))] = {};
323
324 struct kdbus_cmd_hello *hello = (struct kdbus_cmd_hello*) h;
325
6629161f
LP
326 int r;
327
328 assert(b);
329
f08838da
LP
330 if (b->is_server)
331 return -EINVAL;
332
fd8d62d9 333 if (!b->kdbus_buffer) {
13019ef5 334 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
fd8d62d9
LP
335 if (b->kdbus_buffer == MAP_FAILED) {
336 b->kdbus_buffer = NULL;
337 return -errno;
338 }
339 }
340
341 hello->size = sizeof(h);
342 hello->conn_flags =
343 KDBUS_HELLO_ACCEPT_FD|
344 KDBUS_HELLO_ATTACH_COMM|
345 KDBUS_HELLO_ATTACH_EXE|
346 KDBUS_HELLO_ATTACH_CMDLINE|
347 KDBUS_HELLO_ATTACH_CGROUP|
348 KDBUS_HELLO_ATTACH_CAPS|
349 KDBUS_HELLO_ATTACH_SECLABEL|
350 KDBUS_HELLO_ATTACH_AUDIT;
351
13019ef5 352 hello->items[0].type = KDBUS_HELLO_POOL;
fd8d62d9
LP
353 hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
354 hello->items[0].vec.address = (uint64_t) b->kdbus_buffer;
13019ef5 355 hello->items[0].vec.size = KDBUS_POOL_SIZE;
fd8d62d9
LP
356
357 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
6629161f
LP
358 if (r < 0)
359 return -errno;
360
5b7d4c1c
LP
361 /* The higher 32bit of both flags fields are considered
362 * 'incompatible flags'. Refuse them all for now. */
fd8d62d9
LP
363 if (hello->bus_flags > 0xFFFFFFFFULL ||
364 hello->conn_flags > 0xFFFFFFFFULL)
5b7d4c1c
LP
365 return -ENOTSUP;
366
fd8d62d9 367 if (hello->bloom_size != BLOOM_SIZE)
a56f19c4
LP
368 return -ENOTSUP;
369
fd8d62d9 370 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
de297575
LP
371 return -ENOMEM;
372
6629161f 373 b->is_kernel = true;
f08838da 374 b->bus_client = true;
9097fe29 375 b->can_fds = true;
6629161f
LP
376
377 r = bus_start_running(b);
378 if (r < 0)
379 return r;
380
381 return 1;
382}
383
384int bus_kernel_connect(sd_bus *b) {
385 assert(b);
386 assert(b->input_fd < 0);
387 assert(b->output_fd < 0);
388 assert(b->kernel);
389
f08838da
LP
390 if (b->is_server)
391 return -EINVAL;
392
6629161f 393 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
c320885c 394 if (b->input_fd < 0)
6629161f
LP
395 return -errno;
396
397 b->output_fd = b->input_fd;
398
399 return bus_kernel_take_fd(b);
400}
401
402int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
403 int r;
404
405 assert(bus);
406 assert(m);
407 assert(bus->state == BUS_RUNNING);
408
5b7d4c1c 409 r = bus_message_setup_kmsg(bus, m);
6629161f
LP
410 if (r < 0)
411 return r;
412
413 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
414 if (r < 0)
415 return errno == EAGAIN ? 0 : -errno;
416
51038c03 417 return 1;
6629161f
LP
418}
419
fd8d62d9 420static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
febfd508 421 struct kdbus_item *d;
6629161f 422
fd8d62d9
LP
423 assert(bus);
424 assert(k);
425
426 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, k);
427
6133cee2 428 KDBUS_ITEM_FOREACH(d, k) {
6629161f 429
1307c3ff
LP
430 if (d->type == KDBUS_MSG_FDS)
431 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
432 else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD)
433 close_nointr_nofail(d->memfd.fd);
6629161f
LP
434 }
435}
436
437static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
438 sd_bus_message *m = NULL;
febfd508 439 struct kdbus_item *d;
1307c3ff 440 unsigned n_fds = 0;
6629161f
LP
441 _cleanup_free_ int *fds = NULL;
442 struct bus_header *h = NULL;
443 size_t total, n_bytes = 0, idx = 0;
69aec65c 444 const char *destination = NULL, *seclabel = NULL;
6629161f
LP
445 int r;
446
447 assert(bus);
448 assert(k);
449 assert(ret);
450
451 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
452 return 0;
453
6133cee2 454 KDBUS_ITEM_FOREACH(d, k) {
6629161f
LP
455 size_t l;
456
febfd508 457 l = d->size - offsetof(struct kdbus_item, data);
6629161f 458
fd8d62d9 459 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
6629161f
LP
460
461 if (!h) {
9b05bc48 462 h = UINT64_TO_PTR(d->vec.address);
c91cb83c
LP
463
464 if (!bus_header_is_complete(h, d->vec.size))
465 return -EBADMSG;
6629161f
LP
466 }
467
fd8d62d9 468 n_bytes += d->vec.size;
6629161f 469
1307c3ff
LP
470 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
471
472 if (!h)
473 return -EBADMSG;
474
475 n_bytes += d->memfd.size;
476
fd8d62d9 477 } else if (d->type == KDBUS_MSG_FDS) {
6629161f
LP
478 int *f;
479 unsigned j;
480
481 j = l / sizeof(int);
482 f = realloc(fds, sizeof(int) * (n_fds + j));
483 if (!f)
484 return -ENOMEM;
485
486 fds = f;
9097fe29 487 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
6629161f 488 n_fds += j;
f9be01f3 489
1307c3ff 490 } else if (d->type == KDBUS_MSG_SRC_SECLABEL)
69aec65c 491 seclabel = d->str;
6629161f
LP
492 }
493
494 if (!h)
495 return -EBADMSG;
496
c91cb83c 497 r = bus_header_message_size(h, &total);
6629161f
LP
498 if (r < 0)
499 return r;
500
501 if (n_bytes != total)
502 return -EBADMSG;
503
69aec65c 504 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
6629161f
LP
505 if (r < 0)
506 return r;
507
6133cee2 508 KDBUS_ITEM_FOREACH(d, k) {
6629161f
LP
509 size_t l;
510
febfd508 511 l = d->size - offsetof(struct kdbus_item, data);
6629161f 512
fd8d62d9 513 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
bc7fd8cd 514 size_t begin_body;
fd8d62d9 515
c91cb83c 516 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
bc7fd8cd
LP
517
518 if (idx + d->vec.size > begin_body) {
519 struct bus_body_part *part;
520
521 /* Contains body material */
522
523 part = message_append_part(m);
524 if (!part) {
1307c3ff
LP
525 r = -ENOMEM;
526 goto fail;
bc7fd8cd
LP
527 }
528
529 if (idx >= begin_body) {
c91cb83c 530 part->data = UINT64_TO_PTR(d->vec.address);
bc7fd8cd
LP
531 part->size = d->vec.size;
532 } else {
453a0c29 533 part->data = d->vec.address != 0 ? (uint8_t*) UINT64_TO_PTR(d->vec.address) + (begin_body - idx) : NULL;
bc7fd8cd
LP
534 part->size = d->vec.size - (begin_body - idx);
535 }
536
453a0c29 537 part->is_zero = d->vec.address == 0;
bc7fd8cd
LP
538 part->sealed = true;
539 }
fd8d62d9
LP
540
541 idx += d->vec.size;
1307c3ff
LP
542 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
543 struct bus_body_part *part;
544
545 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
546 r = -EBADMSG;
547 goto fail;
548 }
549
550 part = message_append_part(m);
551 if (!part) {
552 r = -ENOMEM;
553 goto fail;
554 }
555
556 part->memfd = d->memfd.fd;
557 part->size = d->memfd.size;
558 part->sealed = true;
559
560 idx += d->memfd.size;
69aec65c 561
69aec65c
LP
562 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
563 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
564 m->uid = d->creds.uid;
565 m->gid = d->creds.gid;
566 m->pid = d->creds.pid;
567 m->tid = d->creds.tid;
568 m->uid_valid = m->gid_valid = true;
569 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
570 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
571 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
572 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
573 m->comm = d->str;
574 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
575 m->tid_comm = d->str;
576 else if (d->type == KDBUS_MSG_SRC_EXE)
577 m->exe = d->str;
77930f11
LP
578 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
579 m->cmdline = d->str;
580 m->cmdline_length = l;
4a875b61
LP
581 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
582 m->cgroup = d->str;
120f919e
LP
583 else if (d->type == KDBUS_MSG_SRC_AUDIT)
584 m->audit = &d->audit;
102ea8e4
LP
585 else if (d->type == KDBUS_MSG_SRC_CAPS) {
586 m->capability = d->data;
587 m->capability_size = l;
1307c3ff
LP
588 } else if (d->type == KDBUS_MSG_DST_NAME)
589 destination = d->str;
590 else if (d->type != KDBUS_MSG_FDS &&
fd8d62d9 591 d->type != KDBUS_MSG_SRC_SECLABEL)
77930f11 592 log_debug("Got unknown field from kernel %llu", d->type);
69aec65c 593 }
acb5a3cb 594
6629161f 595 r = bus_message_parse_fields(m);
1307c3ff
LP
596 if (r < 0)
597 goto fail;
6629161f 598
51038c03
LP
599 if (k->src_id == KDBUS_SRC_ID_KERNEL)
600 m->sender = "org.freedesktop.DBus";
601 else {
602 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
603 m->sender = m->sender_buffer;
604 }
605
606 if (!m->destination) {
607 if (destination)
608 m->destination = destination;
609 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
610 k->dst_id != KDBUS_DST_ID_BROADCAST) {
611 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
612 m->destination = m->destination_buffer;
613 }
614 }
615
6629161f
LP
616 /* We take possession of the kmsg struct now */
617 m->kdbus = k;
fd8d62d9
LP
618 m->bus = sd_bus_ref(bus);
619 m->release_kdbus = true;
6629161f
LP
620 m->free_fds = true;
621
622 fds = NULL;
623
624 *ret = m;
625 return 1;
1307c3ff
LP
626
627fail:
628 if (m) {
629 struct bus_body_part *part;
630 unsigned i;
631
632 /* Make sure the memfds are not freed twice */
633 MESSAGE_FOREACH_PART(part, i, m)
634 if (part->memfd >= 0)
635 part->memfd = -1;
636
637 sd_bus_message_unref(m);
638 }
639
640 return r;
6629161f
LP
641}
642
643int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
644 struct kdbus_msg *k;
6629161f
LP
645 int r;
646
647 assert(bus);
648 assert(m);
649
fd8d62d9
LP
650 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &k);
651 if (r < 0) {
6629161f
LP
652 if (errno == EAGAIN)
653 return 0;
654
fd8d62d9 655 return -errno;
6629161f
LP
656 }
657
658 r = bus_kernel_make_message(bus, k, m);
fd8d62d9
LP
659 if (r <= 0)
660 close_kdbus_msg(bus, k);
6629161f 661
51038c03 662 return r < 0 ? r : 1;
6629161f
LP
663}
664
665int bus_kernel_create(const char *name, char **s) {
5b7d4c1c 666 struct kdbus_cmd_bus_make *make;
febfd508 667 struct kdbus_item *n, *cg;
6629161f
LP
668 size_t l;
669 int fd;
670 char *p;
671
672 assert(name);
673 assert(s);
674
675 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
676 if (fd < 0)
677 return -errno;
678
679 l = strlen(name);
a2cef833 680 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
febfd508
KS
681 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
682 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
a2cef833
KS
683
684 cg = make->items;
799e7ea8 685 cg->type = KDBUS_MAKE_CGROUP;
a2cef833 686 cg->data64[0] = 1;
febfd508 687 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
a2cef833
KS
688
689 n = KDBUS_ITEM_NEXT(cg);
799e7ea8 690 n->type = KDBUS_MAKE_NAME;
a2cef833 691 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
febfd508 692 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
a2cef833
KS
693
694 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
18cd014f 695 make->flags = KDBUS_MAKE_POLICY_OPEN;
5b7d4c1c 696 make->bus_flags = 0;
a56f19c4 697 make->bloom_size = BLOOM_SIZE;
a56f19c4 698 assert_cc(BLOOM_SIZE % 8 == 0);
5b7d4c1c 699
a2cef833 700 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
6629161f
LP
701 if (!p)
702 return -ENOMEM;
703
5b7d4c1c 704 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
6629161f
LP
705 close_nointr_nofail(fd);
706 free(p);
707 return -errno;
708 }
709
710 if (s)
711 *s = p;
712
713 return fd;
714}
bc7fd8cd
LP
715
716int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
717 struct memfd_cache *c;
718
719 assert(address);
720 assert(size);
721
722 if (!bus || !bus->is_kernel)
723 return -ENOTSUP;
724
725 if (bus->n_memfd_cache <= 0) {
9b05bc48 726 int fd, r;
bc7fd8cd 727
9b05bc48
LP
728 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
729 if (r < 0)
bc7fd8cd
LP
730 return -errno;
731
732 *address = NULL;
733 *size = 0;
734 return fd;
735 }
736
737 c = &bus->memfd_cache[-- bus->n_memfd_cache];
738
739 assert(c->fd >= 0);
740 assert(c->size == 0 || c->address);
741
742 *address = c->address;
743 *size = c->size;
744
745 return c->fd;
746}
747
748void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
749 struct memfd_cache *c;
750
751 assert(fd >= 0);
752 assert(size == 0 || address);
753
754 if (!bus || !bus->is_kernel ||
755 bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
756
757 if (size > 0)
758 assert_se(munmap(address, PAGE_ALIGN(size)) == 0);
759
760 close_nointr_nofail(fd);
761 return;
762 }
763
764 c = &bus->memfd_cache[bus->n_memfd_cache++];
765 c->fd = fd;
766 c->address = address;
767
768 /* If overly long, let's return a bit to the OS */
769 if (size > MEMFD_CACHE_ITEM_SIZE_MAX) {
770 uint64_t sz = MEMFD_CACHE_ITEM_SIZE_MAX;
771
772 ioctl(bus->input_fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
773
774 c->size = MEMFD_CACHE_ITEM_SIZE_MAX;
775 } else
776 c->size = size;
777}
778
779void bus_kernel_flush_memfd(sd_bus *b) {
780 unsigned i;
781
782 assert(b);
783
784 for (i = 0; i < b->n_memfd_cache; i++) {
785 if (b->memfd_cache[i].size > 0)
786 assert_se(munmap(b->memfd_cache[i].address, PAGE_ALIGN(b->memfd_cache[i].size)) == 0);
787
788 close_nointr_nofail(b->memfd_cache[i].fd);
789 }
790}