diff options
-rw-r--r-- | src/core/selinux-access.c | 2 | ||||
-rw-r--r-- | src/journal/journald-stream.c | 32 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-control.c | 6 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-creds.c | 13 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-internal.h | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-socket.c | 87 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/sd-bus.c | 1 | ||||
-rw-r--r-- | src/test/test-copy.c | 35 |
8 files changed, 75 insertions, 103 deletions
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c index 5e9a4a5e02..decd42f95a 100644 --- a/src/core/selinux-access.c +++ b/src/core/selinux-access.c @@ -261,7 +261,7 @@ int mac_selinux_generic_access_check( audit_info.path = path; audit_info.cmdline = cl; - r = selinux_check_access((security_context_t) scon, fcon, tclass, permission, &audit_info); + r = selinux_check_access(scon, fcon, tclass, permission, &audit_info); if (r < 0) r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access."); diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index b572147a56..db2f581972 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -59,10 +59,7 @@ struct StdoutStream { int fd; struct ucred ucred; -#ifdef HAVE_SELINUX - security_context_t security_context; -#endif - + char *label; char *identifier; char *unit_id; int priority; @@ -99,12 +96,7 @@ void stdout_stream_free(StdoutStream *s) { } safe_close(s->fd); - -#ifdef HAVE_SELINUX - if (s->security_context) - freecon(s->security_context); -#endif - + free(s->label); free(s->identifier); free(s->unit_id); free(s->state_file); @@ -225,8 +217,7 @@ static int stdout_stream_log(StdoutStream *s, const char *p) { char syslog_facility[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1]; _cleanup_free_ char *message = NULL, *syslog_identifier = NULL; unsigned n = 0; - char *label = NULL; - size_t label_len = 0; + size_t label_len; assert(s); assert(p); @@ -271,14 +262,8 @@ static int stdout_stream_log(StdoutStream *s, const char *p) { if (message) IOVEC_SET_STRING(iovec[n++], message); -#ifdef HAVE_SELINUX - if (s->security_context) { - label = (char*) s->security_context; - label_len = strlen((char*) s->security_context); - } -#endif - - server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority, 0); + label_len = s->label ? strlen(s->label) : 0; + server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, s->label, label_len, s->unit_id, priority, 0); return 0; } @@ -489,12 +474,11 @@ static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { if (r < 0) return log_error_errno(r, "Failed to determine peer credentials: %m"); -#ifdef HAVE_SELINUX if (mac_selinux_use()) { - if (getpeercon(fd, &stream->security_context) < 0 && errno != ENOPROTOOPT) - log_error_errno(errno, "Failed to determine peer security context: %m"); + r = getpeersec(fd, &stream->label); + if (r < 0 && r != -EOPNOTSUPP) + (void) log_warning_errno(r, "Failed to determine peer security context: %m"); } -#endif (void) shutdown(fd, SHUT_WR); diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index b4ca177f76..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-creds.c b/src/libsystemd/sd-bus/bus-creds.c index 4d67619cf8..1c365b7fcd 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -773,11 +773,13 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { return 0; /* Try to retrieve PID from creds if it wasn't passed to us */ - if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID)) + if (pid > 0) { + c->pid = pid; + c->mask |= SD_BUS_CREDS_PID; + } else if (c->mask & SD_BUS_CREDS_PID) pid = c->pid; - - /* Without pid we cannot do much... */ - if (pid <= 0) + else + /* Without pid we cannot do much... */ return 0; /* Try to retrieve TID from creds if it wasn't passed to us */ @@ -789,9 +791,6 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { if (missing == 0) return 0; - c->pid = pid; - c->mask |= SD_BUS_CREDS_PID; - if (tid > 0) { c->tid = tid; c->mask |= SD_BUS_CREDS_TID; 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 5209db8c4d..9f3756f0c2 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); @@ -622,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) { @@ -941,9 +914,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 +961,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 +987,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) diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 598b1be8a6..2805b29839 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -131,6 +131,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); diff --git a/src/test/test-copy.c b/src/test/test-copy.c index 403d85bff0..e55ffaa16a 100644 --- a/src/test/test-copy.c +++ b/src/test/test-copy.c @@ -133,10 +133,45 @@ static void test_copy_tree(void) { (void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL); } +static void test_copy_bytes(void) { + _cleanup_close_pair_ int pipefd[2] = {-1, -1}; + _cleanup_close_ int infd = -1; + int r, r2; + char buf[1024], buf2[1024]; + + infd = open("/etc/os-release", O_RDONLY|O_CLOEXEC); + assert_se(infd >= 0); + + assert_se(pipe2(pipefd, O_CLOEXEC) == 0); + + r = copy_bytes(infd, pipefd[1], (off_t) -1, false); + assert_se(r == 0); + + r = read(pipefd[0], buf, sizeof(buf)); + assert_se(r >= 0); + + assert_se(lseek(infd, 0, SEEK_SET) == 0); + r2 = read(infd, buf2, sizeof(buf2)); + assert_se(r == r2); + + assert_se(strneq(buf, buf2, r)); + + /* test copy_bytes with invalid descriptors */ + r = copy_bytes(pipefd[0], pipefd[0], 1, false); + assert_se(r == -EBADF); + + r = copy_bytes(pipefd[1], pipefd[1], 1, false); + assert_se(r == -EBADF); + + r = copy_bytes(pipefd[1], infd, 1, false); + assert_se(r == -EBADF); +} + int main(int argc, char *argv[]) { test_copy_file(); test_copy_file_fd(); test_copy_tree(); + test_copy_bytes(); return 0; } |