From ea8f194f4b402774aafb9bc3c3ea1c0f288f12a7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 1 Apr 2013 03:25:31 +0200 Subject: [PATCH] bus: be more careful when determining credential data As it turns out SCM_CREDENTIALS is not always supported on socketpair(), so let's also try SO_PEERCRED then. --- src/libsystemd-bus/bus-socket.c | 35 +++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/libsystemd-bus/bus-socket.c b/src/libsystemd-bus/bus-socket.c index 82e683a957..5b5a731233 100644 --- a/src/libsystemd-bus/bus-socket.c +++ b/src/libsystemd-bus/bus-socket.c @@ -513,16 +513,23 @@ static int bus_socket_read_auth(sd_bus *b) { cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - memcpy(&b->ucred, CMSG_DATA(cmsg), sizeof(struct ucred)); - b->ucred_valid = true; + /* 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); - memcpy(&b->label, CMSG_DATA(cmsg), l); - b->label[l] = 0; + if (l > 0) { + memcpy(&b->label, CMSG_DATA(cmsg), l); + b->label[l] = 0; + } } } } @@ -536,6 +543,7 @@ static int bus_socket_read_auth(sd_bus *b) { static int bus_socket_setup(sd_bus *b) { int enable; + socklen_t l; assert(b); @@ -549,6 +557,11 @@ static int bus_socket_setup(sd_bus *b) { fd_inc_rcvbuf(b->input_fd, 1024*1024); fd_inc_sndbuf(b->output_fd, 1024*1024); + /* Get the peer for socketpair() sockets */ + l = sizeof(b->ucred); + if (getsockopt(b->input_fd, SOL_SOCKET, SO_PEERCRED, &b->ucred, &l) >= 0 && l >= sizeof(b->ucred)) + b->ucred_valid = b->ucred.pid > 0; + return 0; } @@ -940,16 +953,22 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) { 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; + /* 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); - memcpy(&bus->label, CMSG_DATA(cmsg), l); - bus->label[l] = 0; + if (l > 0) { + memcpy(&bus->label, CMSG_DATA(cmsg), l); + bus->label[l] = 0; + } } } }