chiark / gitweb /
bus: implicitly collect ucred/label information
authorLennart Poettering <lennart@poettering.net>
Fri, 22 Mar 2013 02:36:58 +0000 (03:36 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 Mar 2013 02:37:10 +0000 (03:37 +0100)
src/libsystemd-bus/bus-internal.h
src/libsystemd-bus/bus-message.c
src/libsystemd-bus/bus-message.h
src/libsystemd-bus/sd-bus.c
src/libsystemd-bus/sd-bus.h
src/libsystemd-bus/test-bus-chat.c
src/libsystemd-bus/test-bus-marshal.c

index c5bd3788b47b68f1b460b4cfa9680139fadde8d7..56514aebbc7220a26d6aa272f0b9a740e36aa992 100644 (file)
@@ -62,6 +62,7 @@ struct sd_bus {
         int message_version;
         bool can_fds:1;
         bool sent_hello:1;
+        bool ucred_valid:1;
 
         void *rbuffer;
         size_t rbuffer_size;
@@ -101,6 +102,9 @@ struct sd_bus {
         size_t auth_size;
         char *auth_uid;
         usec_t auth_timeout;
+
+        struct ucred ucred;
+        char label[NAME_MAX];
 };
 
 static inline void bus_unrefp(sd_bus **b) {
index 74ea71ec0d62bb6749898a384c0d993ed785c63f..01213e31ad9cf4868798a7dca6fbf9c3ae779eda 100644 (file)
@@ -224,10 +224,16 @@ static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x)
         return 0;
 }
 
-int bus_message_from_malloc(void *buffer, size_t length, sd_bus_message **ret) {
+int bus_message_from_malloc(
+                void *buffer,
+                size_t length,
+                struct ucred *ucred,
+                const char *label,
+                sd_bus_message **ret) {
+
         sd_bus_message *m;
         struct bus_header *h;
-        size_t total, fs, bs;
+        size_t total, fs, bs, label_sz, a;
         int r;
 
         assert(buffer || length <= 0);
@@ -259,7 +265,13 @@ int bus_message_from_malloc(void *buffer, size_t length, sd_bus_message **ret) {
         if (length != total)
                 return -EBADMSG;
 
-        m = new0(sd_bus_message, 1);
+        if (label) {
+                label_sz = strlen(label);
+                a = ALIGN(sizeof(sd_bus_message)) + label_sz + 1;
+        } else
+                a = sizeof(sd_bus_message);
+
+        m = malloc0(a);
         if (!m)
                 return -ENOMEM;
 
@@ -270,6 +282,18 @@ int bus_message_from_malloc(void *buffer, size_t length, sd_bus_message **ret) {
         m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN_TO(fs, 8);
         m->sealed = true;
 
+        if (ucred) {
+                m->uid = ucred->uid;
+                m->pid = ucred->pid;
+                m->gid = ucred->gid;
+                m->uid_valid = m->gid_valid = true;
+        }
+
+        if (label) {
+                m->label = (char*) m + ALIGN(sizeof(sd_bus_message));
+                memcpy(m->label, label, label_sz + 1);
+        }
+
         m->n_iovec = 1;
         m->iovec[0].iov_base = buffer;
         m->iovec[0].iov_len = length;
@@ -629,6 +653,13 @@ int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
         return 0;
 }
 
+const char *sd_bus_message_get_label(sd_bus_message *m) {
+        if (!m)
+                return NULL;
+
+        return m->label;
+}
+
 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
         if (!m)
                 return -EINVAL;
index ed1a4b87b1bab59b7f825f15e8d3bac09b12b4da..b21fdf0adab2541c8a09e24ccc8a55e14ab3e45a 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <stdbool.h>
 #include <byteswap.h>
+#include <sys/socket.h>
 
 #include "macro.h"
 #include "sd-bus.h"
@@ -77,6 +78,8 @@ struct sd_bus_message {
         void *fields;
         void *body;
 
+        char *label;
+
         size_t rindex;
 
         uint32_t n_fds;
@@ -127,5 +130,5 @@ static inline void bus_message_unrefp(sd_bus_message **m) {
 int bus_message_seal(sd_bus_message *m, uint64_t serial);
 int bus_message_dump(sd_bus_message *m);
 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz);
-int bus_message_from_malloc(void *buffer, size_t length, sd_bus_message **ret);
+int bus_message_from_malloc(void *buffer, size_t length, struct ucred *ucred, const char *label, sd_bus_message **ret);
 int bus_message_read_strv_extend(sd_bus_message *m, char ***l);
index 09ea01b951545283b365740d54f9d84affb7fde1..73774ba308c67430160892ab17bf4f7931426a87 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "util.h"
 #include "macro.h"
+#include "missing.h"
 
 #include "sd-bus.h"
 #include "bus-internal.h"
@@ -530,6 +531,24 @@ static int bus_read_auth(sd_bus *b) {
         return 1;
 }
 
+static int bus_setup_fd(sd_bus *b) {
+        int one;
+
+        assert(b);
+
+        /* Enable SO_PASSCRED + SO_PASSEC. We try this on any socket,
+         * just in case. This is actually irrelavant for */
+        one = 1;
+        setsockopt(b->fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
+        setsockopt(b->fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
+
+        /* Increase the buffers to a MB */
+        fd_inc_rcvbuf(b->fd, 1024*1024);
+        fd_inc_sndbuf(b->fd, 1024*1024);
+
+        return 0;
+}
+
 static int bus_start_auth(sd_bus *b) {
         static const char auth_prefix[] = "\0AUTH EXTERNAL ";
         static const char auth_suffix[] = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
@@ -578,8 +597,13 @@ static int bus_start_connect(sd_bus *b) {
                 b->fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
                 if (b->fd < 0) {
                         b->last_connect_error = errno;
-                        zero(b->sockaddr);
-                        continue;
+                        goto try_again;
+                }
+
+                r = bus_setup_fd(b);
+                if (r < 0) {
+                        b->last_connect_error = errno;
+                        goto try_again;
                 }
 
                 r = connect(b->fd, &b->sockaddr.sa, b->sockaddr_size);
@@ -588,13 +612,18 @@ static int bus_start_connect(sd_bus *b) {
                                 return 1;
 
                         b->last_connect_error = errno;
-                        close_nointr_nofail(b->fd);
-                        b->fd = -1;
-                        zero(b->sockaddr);
-                        continue;
+                        goto try_again;
                 }
 
                 return bus_start_auth(b);
+
+        try_again:
+                zero(b->sockaddr);
+
+                if (b->fd >= 0) {
+                        close_nointr_nofail(b->fd);
+                        b->fd = -1;
+                }
         }
 }
 
@@ -728,17 +757,29 @@ int sd_bus_open_fd(int fd, sd_bus **ret) {
                 return -ENOMEM;
 
         b->fd = fd;
-        fd_nonblock(b->fd, true);
+
+        r = fd_nonblock(b->fd, true);
+        if (r < 0)
+                goto fail;
+
         fd_cloexec(b->fd, true);
+        if (r < 0)
+                goto fail;
+
+        r = bus_setup_fd(b);
+        if (r < 0)
+                goto fail;
 
         r = bus_start_auth(b);
-        if (r < 0) {
-                bus_free(b);
-                return r;
-        }
+        if (r < 0)
+                goto fail;
 
         *ret = b;
         return 0;
+
+fail:
+                bus_free(b);
+        return r;
 }
 
 void sd_bus_close(sd_bus *bus) {
@@ -930,7 +971,9 @@ static int message_make(sd_bus *bus, size_t size, sd_bus_message **m) {
                 }
         }
 
-        r = bus_message_from_malloc(bus->rbuffer, size, &t);
+        r = bus_message_from_malloc(bus->rbuffer, size,
+                                    bus->ucred_valid ? &bus->ucred : NULL,
+                                    bus->label[0] ? bus->label : NULL, &t);
         if (r < 0) {
                 free(b);
                 return r;
@@ -950,6 +993,12 @@ static int message_read(sd_bus *bus, sd_bus_message **m) {
         size_t need;
         int r;
         void *b;
+        union {
+                struct cmsghdr cmsghdr;
+                uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
+                            CMSG_SPACE(NAME_MAX)]; /*selinux label */
+        } control;
+        struct cmsghdr *cmsg;
 
         assert(bus);
         assert(m);
@@ -975,12 +1024,34 @@ static int message_read(sd_bus *bus, sd_bus_message **m) {
         zero(mh);
         mh.msg_iov = &iov;
         mh.msg_iovlen = 1;
+        mh.msg_control = &control;
+        mh.msg_controllen = sizeof(control);
 
-        k = recvmsg(bus->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
+        k = recvmsg(bus->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
         if (k < 0)
                 return errno == EAGAIN ? 0 : -errno;
 
         bus->rbuffer_size += k;
+        bus->ucred_valid = false;
+        bus->label[0] = 0;
+
+        for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
+                if (cmsg->cmsg_level == SOL_SOCKET &&
+                    cmsg->cmsg_type == SCM_CREDENTIALS &&
+                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+
+                        memcpy(&bus->ucred, CMSG_DATA(cmsg), sizeof(struct ucred));
+                        bus->ucred_valid = true;
+
+                } else if (cmsg->cmsg_level == SOL_SOCKET &&
+                         cmsg->cmsg_type == SCM_SECURITY) {
+
+                        size_t l;
+                        l = cmsg->cmsg_len - CMSG_LEN(0);
+                        memcpy(&bus->label, CMSG_DATA(cmsg), l);
+                        bus->label[l] = 0;
+                }
+        }
 
         r = message_read_need(bus, &need);
         if (r < 0)
index 60f2913d6927c5ce2a11e6e540ee1ea3015a64da..73710d15111fa4d2ec1b8862bbeb60b4c8fc304d 100644 (file)
@@ -106,6 +106,7 @@ int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid);
 int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid);
 int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid);
 int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid);
+const char *sd_bus_message_get_label(sd_bus_message *m);
 
 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member);
 int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member);
index 24a194327ed8b16f3c98e1eaf3010c38e8a58226..23b00c7201f0bd2f092ec5b58cebf2eff916dbc8 100644 (file)
@@ -83,6 +83,7 @@ static int server(sd_bus *bus) {
 
         while (!client1_gone || !client2_gone) {
                 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+                pid_t pid = 0;
 
                 r = sd_bus_process(bus, &m);
                 if (r < 0) {
@@ -103,7 +104,8 @@ static int server(sd_bus *bus) {
                 if (!m)
                         continue;
 
-                log_info("Got message! %s", strna(sd_bus_message_get_member(m)));
+                sd_bus_message_get_pid(m, &pid);
+                log_info("Got message! member=%s pid=%lu label=%s", strna(sd_bus_message_get_member(m)), (unsigned long) pid, strna(sd_bus_message_get_label(m)));
                 /* bus_message_dump(m); */
                 /* sd_bus_message_rewind(m, true); */
 
index d12c847f352140eadde4b0ccf87b330acb65d8be..32bf44fffe292439f702ebb6404ff88b3f5ce86c 100644 (file)
@@ -121,7 +121,7 @@ int main(int argc, char *argv[]) {
 
         m = sd_bus_message_unref(m);
 
-        r = bus_message_from_malloc(buffer, sz, &m);
+        r = bus_message_from_malloc(buffer, sz, NULL, NULL, &m);
         assert_se(r >= 0);
 
         bus_message_dump(m);