summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-05-17 04:25:56 +0200
committerLennart Poettering <lennart@poettering.net>2013-05-17 04:26:27 +0200
commit264ad849a4a0acf1ca392da62b7018d4fe7b66b3 (patch)
tree8748443973e9c40789710e90531ef1dff2d1e40b
parent45fbe937d7ca8d0da9ea276d57bc70ebd41c285e (diff)
bus: add APIs for negotiating what is attached to messages
-rw-r--r--TODO2
-rw-r--r--src/libsystemd-bus/bus-internal.h3
-rw-r--r--src/libsystemd-bus/bus-kernel.c12
-rw-r--r--src/libsystemd-bus/bus-socket.c12
-rw-r--r--src/libsystemd-bus/sd-bus.c92
-rw-r--r--src/libsystemd-bus/test-bus-kernel.c16
-rw-r--r--src/libsystemd-bus/test-bus-server.c4
-rw-r--r--src/shared/macro.h3
-rw-r--r--src/stdio-bridge/stdio-bridge.c4
-rw-r--r--src/systemd/sd-bus.h9
10 files changed, 130 insertions, 27 deletions
diff --git a/TODO b/TODO
index 390106aadf..fb5f0c3813 100644
--- a/TODO
+++ b/TODO
@@ -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
diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h
index 8f87bea781..e775b09419 100644
--- a/src/libsystemd-bus/bus-internal.h
+++ b/src/libsystemd-bus/bus-internal.h
@@ -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) {
diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c
index 699d24185e..107b2bd694 100644
--- a/src/libsystemd-bus/bus-kernel.c
+++ b/src/libsystemd-bus/bus-kernel.c
@@ -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)
diff --git a/src/libsystemd-bus/bus-socket.c b/src/libsystemd-bus/bus-socket.c
index befded7079..b60facb20f 100644
--- a/src/libsystemd-bus/bus-socket.c
+++ b/src/libsystemd-bus/bus-socket.c
@@ -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);
diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index 5e66a31162..6033aa744f 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -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);
diff --git a/src/libsystemd-bus/test-bus-kernel.c b/src/libsystemd-bus/test-bus-kernel.c
index 72514a3dee..b8e89e41bc 100644
--- a/src/libsystemd-bus/test-bus-kernel.c
+++ b/src/libsystemd-bus/test-bus-kernel.c
@@ -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);
diff --git a/src/libsystemd-bus/test-bus-server.c b/src/libsystemd-bus/test-bus-server.c
index a9772624f2..ef26a65d87 100644
--- a/src/libsystemd-bus/test-bus-server.c
+++ b/src/libsystemd-bus/test-bus-server.c
@@ -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);
diff --git a/src/shared/macro.h b/src/shared/macro.h
index 2f151bcc8c..bfe03f2ae0 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -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"
diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c
index a5bdb03416..ab1a43ab1a 100644
--- a/src/stdio-bridge/stdio-bridge.c
+++ b/src/stdio-bridge/stdio-bridge.c
@@ -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;
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 85deacf63f..eeca69dd1a 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -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);