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>
31 #include "bus-internal.h"
32 #include "bus-message.h"
33 #include "bus-kernel.h"
34 #include "bus-bloom.h"
36 #define KDBUS_ITEM_NEXT(item) \
37 (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
39 #define KDBUS_ITEM_FOREACH(item, head) \
40 for (item = (head)->items; \
41 (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \
42 item = KDBUS_ITEM_NEXT(item))
44 #define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
45 #define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
47 static int parse_unique_name(const char *s
, uint64_t *id
) {
53 if (!startswith(s
, ":1."))
56 r
= safe_atou64(s
+ 3, id
);
63 static void append_payload_vec(struct kdbus_item
**d
, const void *p
, size_t sz
) {
70 (*d
)->size
= offsetof(struct kdbus_item
, vec
) + sizeof(struct kdbus_vec
);
71 (*d
)->type
= KDBUS_MSG_PAYLOAD_VEC
;
72 (*d
)->vec
.address
= (intptr_t) p
;
75 *d
= (struct kdbus_item
*) ((uint8_t*) *d
+ (*d
)->size
);
78 static void append_destination(struct kdbus_item
**d
, const char *s
, size_t length
) {
84 (*d
)->size
= offsetof(struct kdbus_item
, str
) + length
+ 1;
85 (*d
)->type
= KDBUS_MSG_DST_NAME
;
86 memcpy((*d
)->str
, s
, length
+ 1);
88 *d
= (struct kdbus_item
*) ((uint8_t*) *d
+ (*d
)->size
);
91 static void* append_bloom(struct kdbus_item
**d
, size_t length
) {
98 (*d
)->size
= offsetof(struct kdbus_item
, data
) + length
;
99 (*d
)->type
= KDBUS_MSG_BLOOM
;
102 *d
= (struct kdbus_item
*) ((uint8_t*) *d
+ (*d
)->size
);
107 static void append_fds(struct kdbus_item
**d
, const int fds
[], unsigned n_fds
) {
113 (*d
)->size
= offsetof(struct kdbus_item
, fds
) + sizeof(int) * n_fds
;
114 (*d
)->type
= KDBUS_MSG_UNIX_FDS
;
115 memcpy((*d
)->fds
, fds
, sizeof(int) * n_fds
);
117 *d
= (struct kdbus_item
*) ((uint8_t*) *d
+ (*d
)->size
);
120 static int bus_message_setup_bloom(sd_bus_message
*m
, void *bloom
) {
127 memset(bloom
, 0, BLOOM_SIZE
);
129 bloom_add_pair(bloom
, "message-type", bus_message_type_to_string(m
->header
->type
));
132 bloom_add_pair(bloom
, "interface", m
->interface
);
134 bloom_add_pair(bloom
, "member", m
->member
);
136 bloom_add_pair(bloom
, "path", m
->path
);
137 bloom_add_prefixes(bloom
, "path-slash-prefix", m
->path
, '/');
140 r
= sd_bus_message_rewind(m
, true);
144 for (i
= 0; i
< 64; i
++) {
147 char buf
[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
150 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
154 if (type
!= SD_BUS_TYPE_STRING
&&
155 type
!= SD_BUS_TYPE_OBJECT_PATH
&&
156 type
!= SD_BUS_TYPE_SIGNATURE
)
159 r
= sd_bus_message_read_basic(m
, type
, &t
);
163 e
= stpcpy(buf
, "arg");
167 *(e
++) = '0' + (i
/ 10);
168 *(e
++) = '0' + (i
% 10);
172 bloom_add_pair(bloom
, buf
, t
);
174 strcpy(e
, "-dot-prefix");
175 bloom_add_prefixes(bloom
, buf
, t
, '.');
176 strcpy(e
, "-slash-prefix");
177 bloom_add_prefixes(bloom
, buf
, t
, '/');
183 static int bus_message_setup_kmsg(sd_bus
*b
, sd_bus_message
*m
) {
184 struct kdbus_item
*d
;
197 if (m
->destination
) {
198 r
= parse_unique_name(m
->destination
, &unique
);
206 sz
= offsetof(struct kdbus_msg
, items
);
208 /* Add in fixed header, fields header and payload */
209 sz
+= 3 * ALIGN8(offsetof(struct kdbus_item
, vec
) + sizeof(struct kdbus_vec
));
211 /* Add space for bloom filter */
212 sz
+= ALIGN8(offsetof(struct kdbus_item
, data
) + BLOOM_SIZE
);
214 /* Add in well-known destination header */
216 dl
= strlen(m
->destination
);
217 sz
+= ALIGN8(offsetof(struct kdbus_item
, str
) + dl
+ 1);
220 /* Add space for unix fds */
222 sz
+= ALIGN8(offsetof(struct kdbus_item
, fds
) + sizeof(int)*m
->n_fds
);
224 m
->kdbus
= memalign(8, sz
);
228 memset(m
->kdbus
, 0, sz
);
231 ((m
->header
->flags
& SD_BUS_MESSAGE_NO_REPLY_EXPECTED
) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY
) |
232 ((m
->header
->flags
& SD_BUS_MESSAGE_NO_AUTO_START
) ? KDBUS_MSG_FLAGS_NO_AUTO_START
: 0);
235 m
->destination
? unique
: KDBUS_DST_ID_BROADCAST
;
236 m
->kdbus
->payload_type
= KDBUS_PAYLOAD_DBUS1
;
237 m
->kdbus
->cookie
= m
->header
->serial
;
239 m
->kdbus
->timeout_ns
= m
->timeout
* NSEC_PER_USEC
;
244 append_destination(&d
, m
->destination
, dl
);
246 append_payload_vec(&d
, m
->header
, sizeof(*m
->header
));
249 append_payload_vec(&d
, m
->fields
, ALIGN8(m
->header
->fields_size
));
252 append_payload_vec(&d
, m
->body
, m
->header
->body_size
);
254 if (m
->kdbus
->dst_id
== KDBUS_DST_ID_BROADCAST
) {
257 p
= append_bloom(&d
, BLOOM_SIZE
);
258 r
= bus_message_setup_bloom(m
, p
);
267 append_fds(&d
, m
->fds
, m
->n_fds
);
269 m
->kdbus
->size
= (uint8_t*) d
- (uint8_t*) m
->kdbus
;
270 assert(m
->kdbus
->size
<= sz
);
272 m
->free_kdbus
= true;
277 int bus_kernel_take_fd(sd_bus
*b
) {
278 struct kdbus_cmd_hello hello
= {
280 KDBUS_HELLO_ACCEPT_FD
|
281 KDBUS_HELLO_ATTACH_COMM
|
282 KDBUS_HELLO_ATTACH_EXE
|
283 KDBUS_HELLO_ATTACH_CMDLINE
|
284 KDBUS_HELLO_ATTACH_CGROUP
|
285 KDBUS_HELLO_ATTACH_CAPS
|
286 KDBUS_HELLO_ATTACH_SECLABEL
|
287 KDBUS_HELLO_ATTACH_AUDIT
296 r
= ioctl(b
->input_fd
, KDBUS_CMD_HELLO
, &hello
);
300 /* The higher 32bit of both flags fields are considered
301 * 'incompatible flags'. Refuse them all for now. */
302 if (hello
.bus_flags
> 0xFFFFFFFFULL
||
303 hello
.conn_flags
> 0xFFFFFFFFULL
)
306 if (hello
.bloom_size
!= BLOOM_SIZE
)
309 if (asprintf(&b
->unique_name
, ":1.%llu", (unsigned long long) hello
.id
) < 0)
313 b
->bus_client
= true;
316 r
= bus_start_running(b
);
323 int bus_kernel_connect(sd_bus
*b
) {
325 assert(b
->input_fd
< 0);
326 assert(b
->output_fd
< 0);
332 b
->input_fd
= open(b
->kernel
, O_RDWR
|O_NOCTTY
|O_CLOEXEC
);
336 b
->output_fd
= b
->input_fd
;
338 return bus_kernel_take_fd(b
);
341 int bus_kernel_write_message(sd_bus
*bus
, sd_bus_message
*m
) {
346 assert(bus
->state
== BUS_RUNNING
);
348 r
= bus_message_setup_kmsg(bus
, m
);
352 r
= ioctl(bus
->output_fd
, KDBUS_CMD_MSG_SEND
, m
->kdbus
);
354 return errno
== EAGAIN
? 0 : -errno
;
359 static void close_kdbus_msg(struct kdbus_msg
*k
) {
360 struct kdbus_item
*d
;
362 KDBUS_ITEM_FOREACH(d
, k
) {
364 if (d
->type
!= KDBUS_MSG_UNIX_FDS
)
367 close_many(d
->fds
, (d
->size
- offsetof(struct kdbus_item
, fds
)) / sizeof(int));
371 static int bus_kernel_make_message(sd_bus
*bus
, struct kdbus_msg
*k
, sd_bus_message
**ret
) {
372 sd_bus_message
*m
= NULL
;
373 struct kdbus_item
*d
;
374 unsigned n_payload
= 0, n_fds
= 0;
375 _cleanup_free_
int *fds
= NULL
;
376 struct bus_header
*h
= NULL
;
377 size_t total
, n_bytes
= 0, idx
= 0;
378 const char *destination
= NULL
, *seclabel
= NULL
;
385 if (k
->payload_type
!= KDBUS_PAYLOAD_DBUS1
)
388 KDBUS_ITEM_FOREACH(d
, k
) {
391 l
= d
->size
- offsetof(struct kdbus_item
, data
);
393 if (d
->type
== KDBUS_MSG_PAYLOAD
) {
396 if (l
< sizeof(struct bus_header
))
399 h
= (struct bus_header
*) d
->data
;
405 } else if (d
->type
== KDBUS_MSG_UNIX_FDS
) {
410 f
= realloc(fds
, sizeof(int) * (n_fds
+ j
));
415 memcpy(fds
+ n_fds
, d
->fds
, sizeof(int) * j
);
418 } else if (d
->type
== KDBUS_MSG_DST_NAME
)
419 destination
= d
->str
;
420 else if (d
->type
== KDBUS_MSG_SRC_SECLABEL
)
427 r
= bus_header_size(h
, &total
);
431 if (n_bytes
!= total
)
434 r
= bus_message_from_header(h
, sizeof(struct bus_header
), fds
, n_fds
, NULL
, seclabel
, 0, &m
);
438 KDBUS_ITEM_FOREACH(d
, k
) {
441 l
= d
->size
- offsetof(struct kdbus_item
, data
);
443 if (d
->type
== KDBUS_MSG_PAYLOAD
) {
445 if (idx
== sizeof(struct bus_header
) &&
446 l
== ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m
)))
448 else if (idx
== sizeof(struct bus_header
) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m
)) &&
449 l
== BUS_MESSAGE_BODY_SIZE(m
))
451 else if (!(idx
== 0 && l
== sizeof(struct bus_header
))) {
452 sd_bus_message_unref(m
);
457 } else if (d
->type
== KDBUS_MSG_SRC_CREDS
) {
458 m
->pid_starttime
= d
->creds
.starttime
/ NSEC_PER_USEC
;
459 m
->uid
= d
->creds
.uid
;
460 m
->gid
= d
->creds
.gid
;
461 m
->pid
= d
->creds
.pid
;
462 m
->tid
= d
->creds
.tid
;
463 m
->uid_valid
= m
->gid_valid
= true;
464 } else if (d
->type
== KDBUS_MSG_TIMESTAMP
) {
465 m
->realtime
= d
->timestamp
.realtime_ns
/ NSEC_PER_USEC
;
466 m
->monotonic
= d
->timestamp
.monotonic_ns
/ NSEC_PER_USEC
;
467 } else if (d
->type
== KDBUS_MSG_SRC_PID_COMM
)
469 else if (d
->type
== KDBUS_MSG_SRC_TID_COMM
)
470 m
->tid_comm
= d
->str
;
471 else if (d
->type
== KDBUS_MSG_SRC_EXE
)
473 else if (d
->type
== KDBUS_MSG_SRC_CMDLINE
) {
475 m
->cmdline_length
= l
;
476 } else if (d
->type
== KDBUS_MSG_SRC_CGROUP
)
478 else if (d
->type
== KDBUS_MSG_SRC_AUDIT
)
479 m
->audit
= &d
->audit
;
480 else if (d
->type
== KDBUS_MSG_SRC_CAPS
) {
481 m
->capability
= d
->data
;
482 m
->capability_size
= l
;
484 log_debug("Got unknown field from kernel %llu", d
->type
);
487 r
= bus_message_parse_fields(m
);
489 sd_bus_message_unref(m
);
493 if (k
->src_id
== KDBUS_SRC_ID_KERNEL
)
494 m
->sender
= "org.freedesktop.DBus";
496 snprintf(m
->sender_buffer
, sizeof(m
->sender_buffer
), ":1.%llu", (unsigned long long) k
->src_id
);
497 m
->sender
= m
->sender_buffer
;
500 if (!m
->destination
) {
502 m
->destination
= destination
;
503 else if (k
->dst_id
!= KDBUS_DST_ID_WELL_KNOWN_NAME
&&
504 k
->dst_id
!= KDBUS_DST_ID_BROADCAST
) {
505 snprintf(m
->destination_buffer
, sizeof(m
->destination_buffer
), ":1.%llu", (unsigned long long) k
->dst_id
);
506 m
->destination
= m
->destination_buffer
;
510 /* We take possession of the kmsg struct now */
512 m
->free_kdbus
= true;
521 int bus_kernel_read_message(sd_bus
*bus
, sd_bus_message
**m
) {
537 k
= bus
->rbuffer
= q
;
540 /* Let's tell valgrind that there's really no need to
541 * initialize this fully. This should be removed again
542 * when valgrind learned the kdbus ioctls natively. */
543 #ifdef HAVE_VALGRIND_MEMCHECK_H
544 VALGRIND_MAKE_MEM_DEFINED(k
, sz
);
547 r
= ioctl(bus
->input_fd
, KDBUS_CMD_MSG_RECV
, bus
->rbuffer
);
554 if (errno
!= ENOBUFS
)
560 r
= bus_kernel_make_message(bus
, k
, m
);
566 return r
< 0 ? r
: 1;
569 int bus_kernel_create(const char *name
, char **s
) {
570 struct kdbus_cmd_bus_make
*make
;
571 struct kdbus_item
*n
, *cg
;
579 fd
= open("/dev/kdbus/control", O_RDWR
|O_NOCTTY
|O_CLOEXEC
);
584 make
= alloca0(offsetof(struct kdbus_cmd_bus_make
, items
) +
585 KDBUS_ITEM_HEADER_SIZE
+ sizeof(uint64_t) +
586 KDBUS_ITEM_HEADER_SIZE
+ DECIMAL_STR_MAX(uid_t
) + 1 + l
+ 1);
589 cg
->type
= KDBUS_MAKE_CGROUP
;
591 cg
->size
= KDBUS_ITEM_HEADER_SIZE
+ sizeof(uint64_t);
593 n
= KDBUS_ITEM_NEXT(cg
);
594 n
->type
= KDBUS_MAKE_NAME
;
595 sprintf(n
->str
, "%lu-%s", (unsigned long) getuid(), name
);
596 n
->size
= KDBUS_ITEM_HEADER_SIZE
+ strlen(n
->str
) + 1;
598 make
->size
= offsetof(struct kdbus_cmd_bus_make
, items
) + cg
->size
+ n
->size
;
599 make
->flags
= KDBUS_MAKE_ACCESS_WORLD
| KDBUS_MAKE_POLICY_OPEN
;
601 make
->bloom_size
= BLOOM_SIZE
;
602 assert_cc(BLOOM_SIZE
% 8 == 0);
604 p
= strjoin("/dev/kdbus/", n
->str
, "/bus", NULL
);
608 if (ioctl(fd
, KDBUS_CMD_BUS_MAKE
, make
) < 0) {
609 close_nointr_nofail(fd
);