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