X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-socket.c;h=bce81aeffce1b8c9584bf178b20f651ac1ba1a27;hp=30e594243d5d62893182f30d21b1600cc22b84c4;hb=f9be01f3b4784affa269694a4f5cdcb87f06f2f7;hpb=8411d2a2b15ec8020cd563162cf1b372d8c0319a diff --git a/src/libsystemd-bus/bus-socket.c b/src/libsystemd-bus/bus-socket.c index 30e594243..bce81aeff 100644 --- a/src/libsystemd-bus/bus-socket.c +++ b/src/libsystemd-bus/bus-socket.c @@ -58,6 +58,39 @@ static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) { } } +static void append_iovec(sd_bus_message *m, const void *p, size_t sz) { + assert(m); + assert(p); + assert(sz > 0); + + m->iovec[m->n_iovec].iov_base = (void*) p; + m->iovec[m->n_iovec].iov_len = sz; + m->n_iovec++; +} + +static void bus_message_setup_iovec(sd_bus_message *m) { + assert(m); + assert(m->sealed); + + if (m->n_iovec > 0) + return; + + append_iovec(m, m->header, sizeof(*m->header)); + + if (m->fields) { + append_iovec(m, m->fields, m->header->fields_size); + + if (m->header->fields_size % 8 != 0) { + static const uint8_t padding[7] = {}; + + append_iovec(m, padding, 8 - (m->header->fields_size % 8)); + } + } + + if (m->body) + append_iovec(m, m->body, m->header->body_size); +} + bool bus_socket_auth_needs_write(sd_bus *b) { unsigned i; @@ -313,13 +346,16 @@ static int bus_socket_auth_verify_server(sd_bus *b) { assert(b); - if (b->rbuffer_size < 3) + if (b->rbuffer_size < 1) return 0; /* First char must be a NUL byte */ if (*(char*) b->rbuffer != 0) return -EIO; + if (b->rbuffer_size < 3) + return 0; + /* Begin with the first line */ if (b->auth_rbegin <= 0) b->auth_rbegin = 1; @@ -452,7 +488,7 @@ static int bus_socket_read_auth(sd_bus *b) { if (r != 0) return r; - n = MAX(256, b->rbuffer_size * 2); + n = MAX(256u, b->rbuffer_size * 2); if (n > BUS_AUTH_SIZE_MAX) n = BUS_AUTH_SIZE_MAX; @@ -510,16 +546,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; + } } } } @@ -533,6 +576,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); @@ -546,6 +590,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; } @@ -713,9 +762,11 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { assert(idx); assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO); - if (*idx >= m->size) + if (*idx >= BUS_MESSAGE_SIZE(m)) return 0; + bus_message_setup_iovec(m); + n = m->n_iovec * sizeof(struct iovec); iov = alloca(n); memcpy(iov, m->iovec, n); @@ -861,7 +912,7 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) { CMSG_SPACE(NAME_MAX)]; /*selinux label */ } control; struct cmsghdr *cmsg; - bool handle_cmsg; + bool handle_cmsg = false; assert(bus); assert(m); @@ -937,16 +988,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; + } } } } @@ -964,16 +1021,14 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) { int bus_socket_process_opening(sd_bus *b) { int error = 0; socklen_t slen = sizeof(error); - struct pollfd p; + struct pollfd p = { + .fd = b->output_fd, + .events = POLLOUT, + }; int r; - assert(b); assert(b->state == BUS_OPENING); - zero(p); - p.fd = b->output_fd; - p.events = POLLOUT; - r = poll(&p, 1, 0); if (r < 0) return -errno;