chiark / gitweb /
bus: add APIs for negotiating what is attached to messages
authorLennart Poettering <lennart@poettering.net>
Fri, 17 May 2013 02:25:56 +0000 (04:25 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 17 May 2013 02:26:27 +0000 (04:26 +0200)
TODO
src/libsystemd-bus/bus-internal.h
src/libsystemd-bus/bus-kernel.c
src/libsystemd-bus/bus-socket.c
src/libsystemd-bus/sd-bus.c
src/libsystemd-bus/test-bus-kernel.c
src/libsystemd-bus/test-bus-server.c
src/shared/macro.h
src/stdio-bridge/stdio-bridge.c
src/systemd/sd-bus.h

diff --git a/TODO b/TODO
index 390106aadffae09449c24a4859a11d9da14e6309..fb5f0c381349c844e69289cc9b73d51684253f27 100644 (file)
--- 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
 
index 8f87bea7815f308316fcd3051a4177bc13dff295..e775b09419d107fddaf92c10a74000dbe70e58d8 100644 (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) {
index 699d24185ea1e1c521fd87c009a58c66030f01bc..107b2bd69401011df9244ad6183f8e59c75ba9c1 100644 (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)
index befded70799e07d242acd30b0f13159924138e93..b60facb20fd642fbb28416e0561611d3afccef51 100644 (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);
index 5e66a31162611ac2d7ae988840aa55950a458320..6033aa744f0d43b591c43e6da6a5ffffa93ff46e 100644 (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);
index 72514a3deee6a8d99b1adad209dd951138b46c6d..b8e89e41bcb45472c8d50b4073b762dc54b7481d 100644 (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);
 
index a9772624f22ee11cb697b5f51775f7a158a5cef2..ef26a65d87023259b9b30bc90002a77d0fcdc882 100644 (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);
 
index 2f151bcc8cb143f5c80d7d33c7de81a2d4c3236f..bfe03f2ae055ce713d07ef16dc53b3cf8a9229bd 100644 (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"
index a5bdb03416315e1f15fbd987cf796779e6deadd0..ab1a43ab1a99f586ccf57499810106e5c2c1d9a6 100644 (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;
index 85deacf63f4a8485aa47382b23019598e2380826..eeca69dd1abb122baa4c28cc9620fe9694521b08 100644 (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);