1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-kernel.h"
35 #include "bus-bloom.h"
37 #define KDBUS_ITEM_NEXT(item) \
38 (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
40 #define KDBUS_ITEM_FOREACH(item, head) \
41 for (item = (head)->items; \
42 (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \
43 item = KDBUS_ITEM_NEXT(item))
45 #define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
46 #define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
48 #define KDBUS_POOL_SIZE (4*1024*1024)
50 static int parse_unique_name(const char *s
, uint64_t *id
) {
56 if (!startswith(s
, ":1."))
59 r
= safe_atou64(s
+ 3, id
);
66 static void append_payload_vec(struct kdbus_item
**d
, const void *p
, size_t sz
) {
73 (*d
)->size
= offsetof(struct kdbus_item
, vec
) + sizeof(struct kdbus_vec
);
74 (*d
)->type
= KDBUS_MSG_PAYLOAD_VEC
;
75 (*d
)->vec
.address
= (uint64_t) p
;
78 *d
= (struct kdbus_item
*) ((uint8_t*) *d
+ (*d
)->size
);
81 static void append_destination(struct kdbus_item
**d
, const char *s
, size_t length
) {
87 (*d
)->size
= offsetof(struct kdbus_item
, str
) + length
+ 1;
88 (*d
)->type
= KDBUS_MSG_DST_NAME
;
89 memcpy((*d
)->str
, s
, length
+ 1);
91 *d
= (struct kdbus_item
*) ((uint8_t*) *d
+ (*d
)->size
);
94 static void* append_bloom(struct kdbus_item
**d
, size_t length
) {
101 (*d
)->size
= offsetof(struct kdbus_item
, data
) + length
;
102 (*d
)->type
= KDBUS_MSG_BLOOM
;
105 *d
= (struct kdbus_item
*) ((uint8_t*) *d
+ (*d
)->size
);
110 static void append_fds(struct kdbus_item
**d
, const int fds
[], unsigned n_fds
) {
116 (*d
)->size
= offsetof(struct kdbus_item
, fds
) + sizeof(int) * n_fds
;
117 (*d
)->type
= KDBUS_MSG_FDS
;
118 memcpy((*d
)->fds
, fds
, sizeof(int) * n_fds
);
120 *d
= (struct kdbus_item
*) ((uint8_t*) *d
+ (*d
)->size
);
123 static int bus_message_setup_bloom(sd_bus_message
*m
, void *bloom
) {
130 memset(bloom
, 0, BLOOM_SIZE
);
132 bloom_add_pair(bloom
, "message-type", bus_message_type_to_string(m
->header
->type
));
135 bloom_add_pair(bloom
, "interface", m
->interface
);
137 bloom_add_pair(bloom
, "member", m
->member
);
139 bloom_add_pair(bloom
, "path", m
->path
);
140 bloom_add_prefixes(bloom
, "path-slash-prefix", m
->path
, '/');
143 r
= sd_bus_message_rewind(m
, true);
147 for (i
= 0; i
< 64; i
++) {
150 char buf
[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
153 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
157 if (type
!= SD_BUS_TYPE_STRING
&&
158 type
!= SD_BUS_TYPE_OBJECT_PATH
&&
159 type
!= SD_BUS_TYPE_SIGNATURE
)
162 r
= sd_bus_message_read_basic(m
, type
, &t
);
166 e
= stpcpy(buf
, "arg");
170 *(e
++) = '0' + (i
/ 10);
171 *(e
++) = '0' + (i
% 10);
175 bloom_add_pair(bloom
, buf
, t
);
177 strcpy(e
, "-dot-prefix");
178 bloom_add_prefixes(bloom
, buf
, t
, '.');
179 strcpy(e
, "-slash-prefix");
180 bloom_add_prefixes(bloom
, buf
, t
, '/');
186 static int bus_message_setup_kmsg(sd_bus
*b
, sd_bus_message
*m
) {
187 struct bus_body_part
*part
;
188 struct kdbus_item
*d
;
202 if (m
->destination
) {
203 r
= parse_unique_name(m
->destination
, &unique
);
211 sz
= offsetof(struct kdbus_msg
, items
);
213 /* Add in fixed header, fields header and payload */
214 sz
+= (1 + m
->n_body_parts
) *
215 ALIGN8(offsetof(struct kdbus_item
, vec
) + sizeof(struct kdbus_vec
));
217 /* Add space for bloom filter */
218 sz
+= ALIGN8(offsetof(struct kdbus_item
, data
) + BLOOM_SIZE
);
220 /* Add in well-known destination header */
222 dl
= strlen(m
->destination
);
223 sz
+= ALIGN8(offsetof(struct kdbus_item
, str
) + dl
+ 1);
226 /* Add space for unix fds */
228 sz
+= ALIGN8(offsetof(struct kdbus_item
, fds
) + sizeof(int)*m
->n_fds
);
230 m
->kdbus
= memalign(8, sz
);
234 memset(m
->kdbus
, 0, sz
);
237 ((m
->header
->flags
& SD_BUS_MESSAGE_NO_REPLY_EXPECTED
) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY
) |
238 ((m
->header
->flags
& SD_BUS_MESSAGE_NO_AUTO_START
) ? KDBUS_MSG_FLAGS_NO_AUTO_START
: 0);
241 m
->destination
? unique
: KDBUS_DST_ID_BROADCAST
;
242 m
->kdbus
->payload_type
= KDBUS_PAYLOAD_DBUS1
;
243 m
->kdbus
->cookie
= m
->header
->serial
;
245 m
->kdbus
->timeout_ns
= m
->timeout
* NSEC_PER_USEC
;
250 append_destination(&d
, m
->destination
, dl
);
252 append_payload_vec(&d
, m
->header
, BUS_MESSAGE_BODY_BEGIN(m
));
253 MESSAGE_FOREACH_PART(part
, i
, m
)
254 append_payload_vec(&d
, part
->data
, part
->size
);
256 if (m
->kdbus
->dst_id
== KDBUS_DST_ID_BROADCAST
) {
259 p
= append_bloom(&d
, BLOOM_SIZE
);
260 r
= bus_message_setup_bloom(m
, p
);
269 append_fds(&d
, m
->fds
, m
->n_fds
);
271 m
->kdbus
->size
= (uint8_t*) d
- (uint8_t*) m
->kdbus
;
272 assert(m
->kdbus
->size
<= sz
);
274 m
->free_kdbus
= true;
279 int bus_kernel_take_fd(sd_bus
*b
) {
280 uint8_t h
[ALIGN8(sizeof(struct kdbus_cmd_hello
)) +
281 ALIGN8(KDBUS_ITEM_HEADER_SIZE
) +
282 ALIGN8(sizeof(struct kdbus_vec
))] = {};
284 struct kdbus_cmd_hello
*hello
= (struct kdbus_cmd_hello
*) h
;
293 if (!b
->kdbus_buffer
) {
294 b
->kdbus_buffer
= mmap(NULL
, KDBUS_POOL_SIZE
, PROT_READ
|PROT_WRITE
, MAP_ANONYMOUS
|MAP_PRIVATE
, -1, 0);
295 if (b
->kdbus_buffer
== MAP_FAILED
) {
296 b
->kdbus_buffer
= NULL
;
301 hello
->size
= sizeof(h
);
303 KDBUS_HELLO_ACCEPT_FD
|
304 KDBUS_HELLO_ATTACH_COMM
|
305 KDBUS_HELLO_ATTACH_EXE
|
306 KDBUS_HELLO_ATTACH_CMDLINE
|
307 KDBUS_HELLO_ATTACH_CGROUP
|
308 KDBUS_HELLO_ATTACH_CAPS
|
309 KDBUS_HELLO_ATTACH_SECLABEL
|
310 KDBUS_HELLO_ATTACH_AUDIT
;
312 hello
->items
[0].type
= KDBUS_HELLO_POOL
;
313 hello
->items
[0].size
= KDBUS_ITEM_HEADER_SIZE
+ sizeof(struct kdbus_vec
);
314 hello
->items
[0].vec
.address
= (uint64_t) b
->kdbus_buffer
;
315 hello
->items
[0].vec
.size
= KDBUS_POOL_SIZE
;
317 r
= ioctl(b
->input_fd
, KDBUS_CMD_HELLO
, hello
);
321 /* The higher 32bit of both flags fields are considered
322 * 'incompatible flags'. Refuse them all for now. */
323 if (hello
->bus_flags
> 0xFFFFFFFFULL
||
324 hello
->conn_flags
> 0xFFFFFFFFULL
)
327 if (hello
->bloom_size
!= BLOOM_SIZE
)
330 if (asprintf(&b
->unique_name
, ":1.%llu", (unsigned long long) hello
->id
) < 0)
334 b
->bus_client
= true;
337 r
= bus_start_running(b
);
344 int bus_kernel_connect(sd_bus
*b
) {
346 assert(b
->input_fd
< 0);
347 assert(b
->output_fd
< 0);
353 b
->input_fd
= open(b
->kernel
, O_RDWR
|O_NOCTTY
|O_CLOEXEC
);
357 b
->output_fd
= b
->input_fd
;
359 return bus_kernel_take_fd(b
);
362 int bus_kernel_write_message(sd_bus
*bus
, sd_bus_message
*m
) {
367 assert(bus
->state
== BUS_RUNNING
);
369 r
= bus_message_setup_kmsg(bus
, m
);
373 r
= ioctl(bus
->output_fd
, KDBUS_CMD_MSG_SEND
, m
->kdbus
);
375 return errno
== EAGAIN
? 0 : -errno
;
380 static void close_kdbus_msg(sd_bus
*bus
, struct kdbus_msg
*k
) {
381 struct kdbus_item
*d
;
386 ioctl(bus
->input_fd
, KDBUS_CMD_MSG_RELEASE
, k
);
388 KDBUS_ITEM_FOREACH(d
, k
) {
390 if (d
->type
!= KDBUS_MSG_FDS
)
393 close_many(d
->fds
, (d
->size
- offsetof(struct kdbus_item
, fds
)) / sizeof(int));
397 static int bus_kernel_make_message(sd_bus
*bus
, struct kdbus_msg
*k
, sd_bus_message
**ret
) {
398 sd_bus_message
*m
= NULL
;
399 struct kdbus_item
*d
;
400 unsigned n_payload
= 0, n_fds
= 0;
401 _cleanup_free_
int *fds
= NULL
;
402 struct bus_header
*h
= NULL
;
403 size_t total
, n_bytes
= 0, idx
= 0;
404 const char *destination
= NULL
, *seclabel
= NULL
;
411 if (k
->payload_type
!= KDBUS_PAYLOAD_DBUS1
)
414 KDBUS_ITEM_FOREACH(d
, k
) {
417 l
= d
->size
- offsetof(struct kdbus_item
, data
);
419 if (d
->type
== KDBUS_MSG_PAYLOAD_VEC
) {
422 h
= UINT64_TO_PTR(d
->vec
.address
);
424 if (!bus_header_is_complete(h
, d
->vec
.size
))
429 n_bytes
+= d
->vec
.size
;
431 } else if (d
->type
== KDBUS_MSG_FDS
) {
436 f
= realloc(fds
, sizeof(int) * (n_fds
+ j
));
441 memcpy(fds
+ n_fds
, d
->fds
, sizeof(int) * j
);
444 } else if (d
->type
== KDBUS_MSG_DST_NAME
)
445 destination
= d
->str
;
446 else if (d
->type
== KDBUS_MSG_SRC_SECLABEL
)
453 r
= bus_header_message_size(h
, &total
);
457 if (n_bytes
!= total
)
460 r
= bus_message_from_header(h
, sizeof(struct bus_header
), fds
, n_fds
, NULL
, seclabel
, 0, &m
);
464 KDBUS_ITEM_FOREACH(d
, k
) {
467 l
= d
->size
- offsetof(struct kdbus_item
, data
);
469 if (d
->type
== KDBUS_MSG_PAYLOAD_VEC
) {
472 begin_body
= BUS_MESSAGE_BODY_BEGIN(m
);
474 if (idx
+ d
->vec
.size
> begin_body
) {
475 struct bus_body_part
*part
;
477 /* Contains body material */
479 part
= message_append_part(m
);
481 sd_bus_message_unref(m
);
485 if (idx
>= begin_body
) {
486 part
->data
= UINT64_TO_PTR(d
->vec
.address
);
487 part
->size
= d
->vec
.size
;
489 part
->data
= d
->vec
.address
!= 0 ? (uint8_t*) UINT64_TO_PTR(d
->vec
.address
) + (begin_body
- idx
) : NULL
;
490 part
->size
= d
->vec
.size
- (begin_body
- idx
);
493 part
->is_zero
= d
->vec
.address
== 0;
499 } else if (d
->type
== KDBUS_MSG_SRC_CREDS
) {
500 m
->pid_starttime
= d
->creds
.starttime
/ NSEC_PER_USEC
;
501 m
->uid
= d
->creds
.uid
;
502 m
->gid
= d
->creds
.gid
;
503 m
->pid
= d
->creds
.pid
;
504 m
->tid
= d
->creds
.tid
;
505 m
->uid_valid
= m
->gid_valid
= true;
506 } else if (d
->type
== KDBUS_MSG_TIMESTAMP
) {
507 m
->realtime
= d
->timestamp
.realtime_ns
/ NSEC_PER_USEC
;
508 m
->monotonic
= d
->timestamp
.monotonic_ns
/ NSEC_PER_USEC
;
509 } else if (d
->type
== KDBUS_MSG_SRC_PID_COMM
)
511 else if (d
->type
== KDBUS_MSG_SRC_TID_COMM
)
512 m
->tid_comm
= d
->str
;
513 else if (d
->type
== KDBUS_MSG_SRC_EXE
)
515 else if (d
->type
== KDBUS_MSG_SRC_CMDLINE
) {
517 m
->cmdline_length
= l
;
518 } else if (d
->type
== KDBUS_MSG_SRC_CGROUP
)
520 else if (d
->type
== KDBUS_MSG_SRC_AUDIT
)
521 m
->audit
= &d
->audit
;
522 else if (d
->type
== KDBUS_MSG_SRC_CAPS
) {
523 m
->capability
= d
->data
;
524 m
->capability_size
= l
;
525 } else if (d
->type
!= KDBUS_MSG_FDS
&&
526 d
->type
!= KDBUS_MSG_DST_NAME
&&
527 d
->type
!= KDBUS_MSG_SRC_SECLABEL
)
528 log_debug("Got unknown field from kernel %llu", d
->type
);
531 r
= bus_message_parse_fields(m
);
533 sd_bus_message_unref(m
);
537 if (k
->src_id
== KDBUS_SRC_ID_KERNEL
)
538 m
->sender
= "org.freedesktop.DBus";
540 snprintf(m
->sender_buffer
, sizeof(m
->sender_buffer
), ":1.%llu", (unsigned long long) k
->src_id
);
541 m
->sender
= m
->sender_buffer
;
544 if (!m
->destination
) {
546 m
->destination
= destination
;
547 else if (k
->dst_id
!= KDBUS_DST_ID_WELL_KNOWN_NAME
&&
548 k
->dst_id
!= KDBUS_DST_ID_BROADCAST
) {
549 snprintf(m
->destination_buffer
, sizeof(m
->destination_buffer
), ":1.%llu", (unsigned long long) k
->dst_id
);
550 m
->destination
= m
->destination_buffer
;
554 /* We take possession of the kmsg struct now */
556 m
->bus
= sd_bus_ref(bus
);
557 m
->release_kdbus
= true;
566 int bus_kernel_read_message(sd_bus
*bus
, sd_bus_message
**m
) {
573 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MSG_RECV
, &k
);
582 /* /\* Let's tell valgrind that there's really no need to */
583 /* * initialize this fully. This should be removed again */
584 /* * when valgrind learned the kdbus ioctls natively. *\/ */
585 /* #ifdef HAVE_VALGRIND_MEMCHECK_H */
586 /* VALGRIND_MAKE_MEM_DEFINED(k, sz); */
590 r
= bus_kernel_make_message(bus
, k
, m
);
592 close_kdbus_msg(bus
, k
);
594 return r
< 0 ? r
: 1;
597 int bus_kernel_create(const char *name
, char **s
) {
598 struct kdbus_cmd_bus_make
*make
;
599 struct kdbus_item
*n
, *cg
;
607 fd
= open("/dev/kdbus/control", O_RDWR
|O_NOCTTY
|O_CLOEXEC
);
612 make
= alloca0(offsetof(struct kdbus_cmd_bus_make
, items
) +
613 KDBUS_ITEM_HEADER_SIZE
+ sizeof(uint64_t) +
614 KDBUS_ITEM_HEADER_SIZE
+ DECIMAL_STR_MAX(uid_t
) + 1 + l
+ 1);
617 cg
->type
= KDBUS_MAKE_CGROUP
;
619 cg
->size
= KDBUS_ITEM_HEADER_SIZE
+ sizeof(uint64_t);
621 n
= KDBUS_ITEM_NEXT(cg
);
622 n
->type
= KDBUS_MAKE_NAME
;
623 sprintf(n
->str
, "%lu-%s", (unsigned long) getuid(), name
);
624 n
->size
= KDBUS_ITEM_HEADER_SIZE
+ strlen(n
->str
) + 1;
626 make
->size
= offsetof(struct kdbus_cmd_bus_make
, items
) + cg
->size
+ n
->size
;
627 make
->flags
= KDBUS_MAKE_POLICY_OPEN
;
629 make
->bloom_size
= BLOOM_SIZE
;
630 assert_cc(BLOOM_SIZE
% 8 == 0);
632 p
= strjoin("/dev/kdbus/", n
->str
, "/bus", NULL
);
636 if (ioctl(fd
, KDBUS_CMD_BUS_MAKE
, make
) < 0) {
637 close_nointr_nofail(fd
);
648 int bus_kernel_pop_memfd(sd_bus
*bus
, void **address
, size_t *size
) {
649 struct memfd_cache
*c
;
654 if (!bus
|| !bus
->is_kernel
)
657 if (bus
->n_memfd_cache
<= 0) {
660 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MEMFD_NEW
, &fd
);
669 c
= &bus
->memfd_cache
[-- bus
->n_memfd_cache
];
672 assert(c
->size
== 0 || c
->address
);
674 *address
= c
->address
;
680 void bus_kernel_push_memfd(sd_bus
*bus
, int fd
, void *address
, size_t size
) {
681 struct memfd_cache
*c
;
684 assert(size
== 0 || address
);
686 if (!bus
|| !bus
->is_kernel
||
687 bus
->n_memfd_cache
>= ELEMENTSOF(bus
->memfd_cache
)) {
690 assert_se(munmap(address
, PAGE_ALIGN(size
)) == 0);
692 close_nointr_nofail(fd
);
696 c
= &bus
->memfd_cache
[bus
->n_memfd_cache
++];
698 c
->address
= address
;
700 /* If overly long, let's return a bit to the OS */
701 if (size
> MEMFD_CACHE_ITEM_SIZE_MAX
) {
702 uint64_t sz
= MEMFD_CACHE_ITEM_SIZE_MAX
;
704 ioctl(bus
->input_fd
, KDBUS_CMD_MEMFD_SIZE_SET
, &sz
);
706 c
->size
= MEMFD_CACHE_ITEM_SIZE_MAX
;
711 void bus_kernel_flush_memfd(sd_bus
*b
) {
716 for (i
= 0; i
< b
->n_memfd_cache
; i
++) {
717 if (b
->memfd_cache
[i
].size
> 0)
718 assert_se(munmap(b
->memfd_cache
[i
].address
, PAGE_ALIGN(b
->memfd_cache
[i
].size
)) == 0);
720 close_nointr_nofail(b
->memfd_cache
[i
].fd
);