bus: add APIs for negotiating what is attached to messages

This commit is contained in:
Lennart Poettering 2013-05-17 04:25:56 +02:00
parent 45fbe937d7
commit 264ad849a4
10 changed files with 130 additions and 27 deletions

2
TODO
View File

@ -35,14 +35,12 @@ Features:
* libsystemd-bus:
- default policy (allow uid == 0 and our own uid)
- enforce alignment of pointers passed in
- negotiation for attach attributes
- when kdbus doesn't take our message without memfds, try again with memfds
- kdbus: generate correct bloom filter for matches
- implement translator service
- port systemd to new library
- implement busname unit type in systemd
- move to gvariant
- keep the connection fds around as long as the bus is open
- merge busctl into systemctl or so?
- synthesize sd_bus_message objects from kernel messages

View File

@ -99,7 +99,6 @@ struct sd_bus {
int message_version;
bool is_kernel:1;
bool negotiate_fds:1;
bool can_fds:1;
bool bus_client:1;
bool ucred_valid:1;
@ -181,6 +180,8 @@ struct sd_bus {
unsigned n_memfd_cache;
pid_t original_pid;
uint64_t hello_flags;
};
static inline void bus_unrefp(sd_bus **b) {

View File

@ -345,15 +345,7 @@ int bus_kernel_take_fd(sd_bus *b) {
}
hello->size = sizeof(h);
hello->conn_flags =
KDBUS_HELLO_ACCEPT_FD|
KDBUS_HELLO_ATTACH_COMM|
KDBUS_HELLO_ATTACH_EXE|
KDBUS_HELLO_ATTACH_CMDLINE|
KDBUS_HELLO_ATTACH_CGROUP|
KDBUS_HELLO_ATTACH_CAPS|
KDBUS_HELLO_ATTACH_SECLABEL|
KDBUS_HELLO_ATTACH_AUDIT;
hello->conn_flags = b->hello_flags;
hello->items[0].type = KDBUS_HELLO_POOL;
hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
@ -378,7 +370,7 @@ int bus_kernel_take_fd(sd_bus *b) {
b->is_kernel = true;
b->bus_client = true;
b->can_fds = true;
b->can_fds = !!(hello->conn_flags & KDBUS_HELLO_ACCEPT_FD);
r = bus_start_running(b);
if (r < 0)

View File

@ -181,7 +181,7 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
if (!e)
return 0;
if (b->negotiate_fds) {
if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD) {
f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
if (!f)
return 0;
@ -464,7 +464,7 @@ static int bus_socket_auth_verify_server(sd_bus *b) {
r = bus_socket_auth_write_ok(b);
}
} else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
if (b->auth == _BUS_AUTH_INVALID || !b->negotiate_fds)
if (b->auth == _BUS_AUTH_INVALID || !(b->hello_flags & KDBUS_HELLO_ACCEPT_FD))
r = bus_socket_auth_write(b, "ERROR\r\n");
else {
b->can_fds = true;
@ -610,6 +610,8 @@ static int bus_socket_setup(sd_bus *b) {
* socket, just in case. */
enable = !b->bus_client;
setsockopt(b->input_fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable));
enable = !b->bus_client && (b->hello_flags & KDBUS_HELLO_ATTACH_SECLABEL);
setsockopt(b->input_fd, SOL_SOCKET, SO_PASSSEC, &enable, sizeof(enable));
/* Increase the buffers to a MB */
@ -651,7 +653,7 @@ static int bus_socket_start_auth_client(sd_bus *b) {
if (!b->auth_buffer)
return -ENOMEM;
if (b->negotiate_fds)
if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD)
auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
else
auth_suffix = "\r\nBEGIN\r\n";
@ -673,11 +675,11 @@ static int bus_socket_start_auth(sd_bus *b) {
b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
b->negotiate_fds = false;
b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
if (b->output_fd != b->input_fd)
if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
b->negotiate_fds = false;
b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
if (b->is_server)
return bus_socket_read_auth(b);

View File

@ -125,7 +125,7 @@ int sd_bus_new(sd_bus **ret) {
r->n_ref = REFCNT_INIT;
r->input_fd = r->output_fd = -1;
r->message_version = 1;
r->negotiate_fds = true;
r->hello_flags |= KDBUS_HELLO_ACCEPT_FD;
r->original_pid = getpid();
assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
@ -226,7 +226,7 @@ int sd_bus_set_bus_client(sd_bus *bus, int b) {
return 0;
}
int sd_bus_set_negotiate_fds(sd_bus *bus, int b) {
int sd_bus_negotiate_fds(sd_bus *bus, int b) {
if (!bus)
return -EINVAL;
if (bus->state != BUS_UNSET)
@ -234,7 +234,91 @@ int sd_bus_set_negotiate_fds(sd_bus *bus, int b) {
if (bus_pid_changed(bus))
return -ECHILD;
bus->negotiate_fds = !!b;
SET_FLAG(bus->hello_flags, KDBUS_HELLO_ACCEPT_FD, b);
return 0;
}
int sd_bus_negotiate_attach_comm(sd_bus *bus, int b) {
if (!bus)
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
if (bus_pid_changed(bus))
return -ECHILD;
SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_COMM, b);
return 0;
}
int sd_bus_negotiate_attach_exe(sd_bus *bus, int b) {
if (!bus)
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
if (bus_pid_changed(bus))
return -ECHILD;
SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_EXE, b);
return 0;
}
int sd_bus_negotiate_attach_cmdline(sd_bus *bus, int b) {
if (!bus)
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
if (bus_pid_changed(bus))
return -ECHILD;
SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CMDLINE, b);
return 0;
}
int sd_bus_negotiate_attach_cgroup(sd_bus *bus, int b) {
if (!bus)
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
if (bus_pid_changed(bus))
return -ECHILD;
SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CGROUP, b);
return 0;
}
int sd_bus_negotiate_attach_caps(sd_bus *bus, int b) {
if (!bus)
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
if (bus_pid_changed(bus))
return -ECHILD;
SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CAPS, b);
return 0;
}
int sd_bus_negotiate_attach_selinux_context(sd_bus *bus, int b) {
if (!bus)
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
if (bus_pid_changed(bus))
return -ECHILD;
SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_SECLABEL, b);
return 0;
}
int sd_bus_negotiate_attach_audit(sd_bus *bus, int b) {
if (!bus)
return -EINVAL;
if (bus->state != BUS_UNSET)
return -EPERM;
if (bus_pid_changed(bus))
return -ECHILD;
SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_AUDIT, b);
return 0;
}
@ -1015,7 +1099,7 @@ int sd_bus_can_send(sd_bus *bus, char type) {
return -ECHILD;
if (type == SD_BUS_TYPE_UNIX_FD) {
if (!bus->negotiate_fds)
if (!(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD))
return 0;
r = bus_ensure_running(bus);

View File

@ -60,6 +60,22 @@ int main(int argc, char *argv[]) {
r = sd_bus_set_address(b, address);
assert_se(r >= 0);
assert_se(sd_bus_negotiate_attach_comm(a, 1) >= 0);
assert_se(sd_bus_negotiate_attach_exe(a, 1) >= 0);
assert_se(sd_bus_negotiate_attach_cmdline(a, 1) >= 0);
assert_se(sd_bus_negotiate_attach_cgroup(a, 1) >= 0);
assert_se(sd_bus_negotiate_attach_caps(a, 1) >= 0);
assert_se(sd_bus_negotiate_attach_selinux_context(a, 1) >= 0);
assert_se(sd_bus_negotiate_attach_audit(a, 1) >= 0);
assert_se(sd_bus_negotiate_attach_comm(b, 1) >= 0);
assert_se(sd_bus_negotiate_attach_exe(b, 1) >= 0);
assert_se(sd_bus_negotiate_attach_cmdline(b, 1) >= 0);
assert_se(sd_bus_negotiate_attach_cgroup(b, 1) >= 0);
assert_se(sd_bus_negotiate_attach_caps(b, 1) >= 0);
assert_se(sd_bus_negotiate_attach_selinux_context(b, 1) >= 0);
assert_se(sd_bus_negotiate_attach_audit(b, 1) >= 0);
r = sd_bus_start(a);
assert_se(r >= 0);

View File

@ -55,8 +55,8 @@ static void *server(void *p) {
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
assert_se(sd_bus_set_server(bus, 1, id) >= 0);
assert_se(sd_bus_set_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
assert_se(sd_bus_start(bus) >= 0);
while (!quit) {
@ -134,7 +134,7 @@ static int client(struct context *c) {
assert_se(sd_bus_new(&bus) >= 0);
assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
assert_se(sd_bus_set_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
assert_se(sd_bus_start(bus) >= 0);

View File

@ -284,4 +284,7 @@ do { \
sizeof(type) <= 4 ? 10 : \
sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
#define SET_FLAG(v, flag, b) \
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
#include "log.h"

View File

@ -68,7 +68,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
r = sd_bus_set_negotiate_fds(a, is_unix);
r = sd_bus_negotiate_fds(a, is_unix);
if (r < 0) {
log_error("Failed to set FD negotiation: %s", strerror(-r));
goto finish;
@ -104,7 +104,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
r = sd_bus_set_negotiate_fds(b, is_unix);
r = sd_bus_negotiate_fds(b, is_unix);
if (r < 0) {
log_error("Failed to set FD negotiation: %s", strerror(-r));
goto finish;

View File

@ -64,7 +64,14 @@ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]);
int sd_bus_set_bus_client(sd_bus *bus, int b);
int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id);
int sd_bus_set_anonymous(sd_bus *bus, int b);
int sd_bus_set_negotiate_fds(sd_bus *bus, int b);
int sd_bus_negotiate_fds(sd_bus *bus, int b);
int sd_bus_negotiate_attach_comm(sd_bus *bus, int b);
int sd_bus_negotiate_attach_exe(sd_bus *bus, int b);
int sd_bus_negotiate_attach_cmdline(sd_bus *bus, int b);
int sd_bus_negotiate_attach_cgroup(sd_bus *bus, int b);
int sd_bus_negotiate_attach_caps(sd_bus *bus, int b);
int sd_bus_negotiate_attach_selinux_context(sd_bus *bus, int b);
int sd_bus_negotiate_attach_audit(sd_bus *bus, int b);
int sd_bus_start(sd_bus *ret);
void sd_bus_close(sd_bus *bus);