From d868f2a3a1cc97b1e081b7692e80a1182efccda4 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 6 Jun 2015 18:59:27 -0400 Subject: sd-bus: do not use per-datagram auxiliary information SELinux information cannot be retrieved this way, since we are using stream unix sockets and SCM_SECURITY does not work for them. SCM_CREDENTIALS use dropped to be consistent. We also should get this information at connection time. https://bugzilla.redhat.com/show_bug.cgi?id=1224211 "SCM_SECURITY was only added for datagram sockets." --- src/libsystemd/sd-bus/bus-socket.c | 80 ++++++-------------------------------- 1 file changed, 12 insertions(+), 68 deletions(-) (limited to 'src/libsystemd/sd-bus/bus-socket.c') diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 4fffc6581d..facfd737e6 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -500,9 +500,7 @@ static int bus_socket_read_auth(sd_bus *b) { void *p; union { struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX) + - CMSG_SPACE(sizeof(struct ucred)) + - CMSG_SPACE(NAME_MAX)]; /*selinux label */ + uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)]; } control; struct cmsghdr *cmsg; bool handle_cmsg = false; @@ -554,8 +552,8 @@ static int bus_socket_read_auth(sd_bus *b) { b->rbuffer_size += k; - if (handle_cmsg) { - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { + if (handle_cmsg) + for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int j; @@ -566,31 +564,9 @@ static int bus_socket_read_auth(sd_bus *b) { j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); close_many((int*) CMSG_DATA(cmsg), j); return -EIO; - - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - - /* Ignore bogus data, which we might - * get on socketpair() sockets */ - if (((struct ucred*) CMSG_DATA(cmsg))->pid != 0) { - memcpy(&b->ucred, CMSG_DATA(cmsg), sizeof(struct ucred)); - b->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); - if (l > 0) { - memcpy(&b->label, CMSG_DATA(cmsg), l); - b->label[l] = 0; - } - } - } - } + } else + log_debug("Got unexpected auxiliary data with level=%d and type=%d", + cmsg->cmsg_level, cmsg->cmsg_type); r = bus_socket_auth_verify(b); if (r != 0) @@ -600,18 +576,8 @@ static int bus_socket_read_auth(sd_bus *b) { } void bus_socket_setup(sd_bus *b) { - int enable; - assert(b); - /* Enable SO_PASSCRED + SO_PASSEC. We try this on any - * socket, just in case. */ - enable = !b->bus_client; - (void) setsockopt(b->input_fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)); - - enable = !b->bus_client && (b->attach_flags & KDBUS_ATTACH_SECLABEL); - (void) setsockopt(b->input_fd, SOL_SOCKET, SO_PASSSEC, &enable, sizeof(enable)); - /* Increase the buffers to 8 MB */ fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE); fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE); @@ -941,9 +907,7 @@ int bus_socket_read_message(sd_bus *bus) { void *b; union { struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX) + - CMSG_SPACE(sizeof(struct ucred)) + - CMSG_SPACE(NAME_MAX)]; /*selinux label */ + uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)]; } control; struct cmsghdr *cmsg; bool handle_cmsg = false; @@ -990,8 +954,8 @@ int bus_socket_read_message(sd_bus *bus) { bus->rbuffer_size += k; - if (handle_cmsg) { - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { + if (handle_cmsg) + for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int n, *f; @@ -1016,29 +980,9 @@ int bus_socket_read_message(sd_bus *bus) { memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int)); bus->fds = f; bus->n_fds += n; - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - - /* Ignore bogus data, which we might - * get on socketpair() sockets */ - if (((struct ucred*) CMSG_DATA(cmsg))->pid != 0) { - 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); - if (l > 0) { - memcpy(&bus->label, CMSG_DATA(cmsg), l); - bus->label[l] = 0; - } - } - } - } + } else + log_debug("Got unexpected auxiliary data with level=%d and type=%d", + cmsg->cmsg_level, cmsg->cmsg_type); r = bus_socket_read_message_need(bus, &need); if (r < 0) -- cgit v1.2.3-54-g00ecf From c4e6556c46cea1b7195cfb81c8cfab8342ebd852 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 6 Jun 2015 21:24:45 -0400 Subject: sd-bus: store selinux context at connection time This appears to be the right time to do it for SOCK_STREAM unix sockets. Also: condition bus_get_owner_creds_dbus1 was reversed. Split it out to a separate variable for clarity and fix. https://bugzilla.redhat.com/show_bug.cgi?id=1224211 --- src/libsystemd/sd-bus/bus-control.c | 6 ++++-- src/libsystemd/sd-bus/bus-internal.h | 2 +- src/libsystemd/sd-bus/bus-socket.c | 7 +++++++ src/libsystemd/sd-bus/sd-bus.c | 1 + 4 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src/libsystemd/sd-bus/bus-socket.c') diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index 43ddfc651d..1103903358 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -979,8 +979,10 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds ** _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; pid_t pid = 0; int r; + bool do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT); - if (!bus->ucred_valid && !isempty(bus->label)) + /* Avoid allocating anything if we have no chance of returning useful data */ + if (!bus->ucred_valid && !do_label) return -ENODATA; c = bus_creds_new(); @@ -1004,7 +1006,7 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds ** } } - if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) { + if (do_label) { c->label = strdup(bus->label); if (!c->label) return -ENOMEM; diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 1351938c80..2ee0eabc02 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -261,7 +261,7 @@ struct sd_bus { usec_t auth_timeout; struct ucred ucred; - char label[NAME_MAX]; + char *label; uint64_t creds_mask; diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index facfd737e6..bcd49efb20 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -588,10 +588,17 @@ void bus_socket_setup(sd_bus *b) { } static void bus_get_peercred(sd_bus *b) { + int r; + assert(b); /* Get the peer for socketpair() sockets */ b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0; + + /* Get the SELinux context of the peer */ + r = getpeersec(b->input_fd, &b->label); + if (r < 0 && r != -EOPNOTSUPP) + log_debug_errno(r, "Failed to determine peer security context: %m"); } static int bus_socket_start_auth_client(sd_bus *b) { diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index edc27aef87..0cd5cad223 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -116,6 +116,7 @@ static void bus_free(sd_bus *b) { if (b->kdbus_buffer) munmap(b->kdbus_buffer, KDBUS_POOL_SIZE); + free(b->label); free(b->rbuffer); free(b->unique_name); free(b->auth_buffer); -- cgit v1.2.3-54-g00ecf