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