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