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