X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-kernel.c;h=f2b130b438a513a1c798dbd3a58c65bed86ffc67;hp=0ece1f014db6e4df12d5b61277f48726c06d8e68;hb=27df44a2c6344da89885dfabac611e5df77b620e;hpb=76b7742c135ad6dac789ee7d27ebf90d188f578b diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index 0ece1f014..f2b130b43 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -313,12 +313,7 @@ fail: } int bus_kernel_take_fd(sd_bus *b) { - uint8_t h[ALIGN8(sizeof(struct kdbus_cmd_hello)) + - ALIGN8(KDBUS_ITEM_HEADER_SIZE) + - ALIGN8(sizeof(struct kdbus_vec))] = {}; - - struct kdbus_cmd_hello *hello = (struct kdbus_cmd_hello*) h; - + struct kdbus_cmd_hello hello; int r; assert(b); @@ -328,41 +323,38 @@ int bus_kernel_take_fd(sd_bus *b) { b->use_memfd = 1; + zero(hello); + hello.size = sizeof(hello); + hello.conn_flags = b->hello_flags; + hello.pool_size = KDBUS_POOL_SIZE; + + r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello); + if (r < 0) + return -errno; + if (!b->kdbus_buffer) { - b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0); if (b->kdbus_buffer == MAP_FAILED) { b->kdbus_buffer = NULL; return -errno; } } - hello->size = sizeof(h); - hello->conn_flags = b->hello_flags; - - hello->items[0].type = KDBUS_HELLO_POOL; - hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); - hello->items[0].vec.address = (uint64_t) b->kdbus_buffer; - hello->items[0].vec.size = KDBUS_POOL_SIZE; - - r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello); - if (r < 0) - return -errno; - /* The higher 32bit of both flags fields are considered * 'incompatible flags'. Refuse them all for now. */ - if (hello->bus_flags > 0xFFFFFFFFULL || - hello->conn_flags > 0xFFFFFFFFULL) + if (hello.bus_flags > 0xFFFFFFFFULL || + hello.conn_flags > 0xFFFFFFFFULL) return -ENOTSUP; - if (hello->bloom_size != BLOOM_SIZE) + if (hello.bloom_size != BLOOM_SIZE) return -ENOTSUP; - if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) + if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0) return -ENOMEM; b->is_kernel = true; b->bus_client = true; - b->can_fds = !!(hello->conn_flags & KDBUS_HELLO_ACCEPT_FD); + b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD); r = bus_start_running(b); if (r < 0) @@ -408,12 +400,14 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) { } static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) { + uint64_t off; struct kdbus_item *d; assert(bus); assert(k); - ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, k); + off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer; + ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off); KDBUS_ITEM_FOREACH(d, k) { @@ -446,10 +440,10 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess l = d->size - offsetof(struct kdbus_item, data); - if (d->type == KDBUS_MSG_PAYLOAD_VEC) { + if (d->type == KDBUS_MSG_PAYLOAD_OFF) { if (!h) { - h = UINT64_TO_PTR(d->vec.address); + h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset); if (!bus_header_is_complete(h, d->vec.size)) return -EBADMSG; @@ -491,7 +485,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess if (n_bytes != total) return -EBADMSG; - r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m); + r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m); if (r < 0) return r; @@ -500,7 +494,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess l = d->size - offsetof(struct kdbus_item, data); - if (d->type == KDBUS_MSG_PAYLOAD_VEC) { + if (d->type == KDBUS_MSG_PAYLOAD_OFF) { size_t begin_body; begin_body = BUS_MESSAGE_BODY_BEGIN(m); @@ -516,15 +510,19 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess goto fail; } + /* A -1 offset is NUL padding. */ + part->is_zero = d->vec.offset == ~0ULL; + if (idx >= begin_body) { - part->data = UINT64_TO_PTR(d->vec.address); + if (!part->is_zero) + part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset; part->size = d->vec.size; } else { - part->data = d->vec.address != 0 ? (uint8_t*) UINT64_TO_PTR(d->vec.address) + (begin_body - idx) : NULL; + if (!part->is_zero) + part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx); part->size = d->vec.size - (begin_body - idx); } - part->is_zero = d->vec.address == 0; part->sealed = true; } @@ -550,35 +548,53 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess idx += d->memfd.size; } else if (d->type == KDBUS_MSG_SRC_CREDS) { - m->pid_starttime = d->creds.starttime / NSEC_PER_USEC; - m->uid = d->creds.uid; - m->gid = d->creds.gid; - m->pid = d->creds.pid; - m->tid = d->creds.tid; - m->uid_valid = m->gid_valid = true; + m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC; + m->creds.uid = d->creds.uid; + m->creds.gid = d->creds.gid; + m->creds.pid = d->creds.pid; + m->creds.tid = d->creds.tid; + m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID) & bus->creds_mask; + } else if (d->type == KDBUS_MSG_TIMESTAMP) { m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC; m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC; - } else if (d->type == KDBUS_MSG_SRC_PID_COMM) - m->comm = d->str; - else if (d->type == KDBUS_MSG_SRC_TID_COMM) - m->tid_comm = d->str; - else if (d->type == KDBUS_MSG_SRC_EXE) - m->exe = d->str; - else if (d->type == KDBUS_MSG_SRC_CMDLINE) { - m->cmdline = d->str; - m->cmdline_length = l; - } else if (d->type == KDBUS_MSG_SRC_CGROUP) - m->cgroup = d->str; - else if (d->type == KDBUS_MSG_SRC_AUDIT) - m->audit = &d->audit; - else if (d->type == KDBUS_MSG_SRC_CAPS) { - m->capability = d->data; - m->capability_size = l; + + } else if (d->type == KDBUS_MSG_SRC_PID_COMM) { + m->creds.comm = d->str; + m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_TID_COMM) { + m->creds.tid_comm = d->str; + m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_EXE) { + m->creds.exe = d->str; + m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_CMDLINE) { + m->creds.cmdline = d->str; + m->creds.cmdline_length = l; + m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_CGROUP) { + m->creds.cgroup = d->str; + m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_AUDIT) { + m->creds.audit_session_id = d->audit.sessionid; + m->creds.audit_login_uid = d->audit.loginuid; + m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask; + + } else if (d->type == KDBUS_MSG_SRC_CAPS) { + m->creds.capability = d->data; + m->creds.capability_size = l; + m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask; + } else if (d->type == KDBUS_MSG_DST_NAME) destination = d->str; else if (d->type != KDBUS_MSG_FDS && - d->type != KDBUS_MSG_SRC_SECLABEL) + d->type != KDBUS_MSG_SRC_SECLABEL && + d->type != KDBUS_MSG_SRC_NAMES) log_debug("Got unknown field from kernel %llu", d->type); } @@ -605,7 +621,6 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess /* We take possession of the kmsg struct now */ m->kdbus = k; - m->bus = sd_bus_ref(bus); m->release_kdbus = true; m->free_fds = true; @@ -631,21 +646,21 @@ fail: } int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) { - uint64_t addr; + uint64_t off; struct kdbus_msg *k; int r; assert(bus); assert(m); - r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &addr); + r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off); if (r < 0) { if (errno == EAGAIN) return 0; return -errno; } - k = UINT64_TO_PTR(addr); + k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off); r = bus_kernel_make_message(bus, k, m); if (r <= 0) @@ -656,7 +671,7 @@ int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) { int bus_kernel_create(const char *name, char **s) { struct kdbus_cmd_bus_make *make; - struct kdbus_item *n, *cg; + struct kdbus_item *n; size_t l; int fd; char *p; @@ -673,17 +688,12 @@ int bus_kernel_create(const char *name, char **s) { KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) + KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1); - cg = make->items; - cg->type = KDBUS_MAKE_CGROUP; - cg->data64[0] = 1; - cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t); - - n = KDBUS_ITEM_NEXT(cg); + n = make->items; n->type = KDBUS_MAKE_NAME; sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name); n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1; - make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size; + make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size; make->flags = KDBUS_MAKE_POLICY_OPEN; make->bus_flags = 0; make->bloom_size = BLOOM_SIZE; @@ -731,7 +741,7 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) { return fd; } - c = &bus->memfd_cache[-- bus->n_memfd_cache]; + c = &bus->memfd_cache[--bus->n_memfd_cache]; assert(c->fd >= 0); assert(c->size == 0 || c->address);