X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibelogind%2Fsd-bus%2Fbus-kernel.c;h=ae53b7dec8cf3072c6267a3b9153f5a7e80fe426;hb=94c5f7fa9e34517edad75cd63d71dd459ec4f133;hp=35c2aa6bee0021c98c7b8154a15664b55d25a0c7;hpb=f48dd74a8d39b6074f820f904953f5cece03b9b0;p=elogind.git diff --git a/src/libelogind/sd-bus/bus-kernel.c b/src/libelogind/sd-bus/bus-kernel.c index 35c2aa6be..ae53b7dec 100644 --- a/src/libelogind/sd-bus/bus-kernel.c +++ b/src/libelogind/sd-bus/bus-kernel.c @@ -29,23 +29,28 @@ #include /* When we include libgen.h because we need dirname() we immediately - * undefine basename() since libgen.h defines it as a macro to the XDG - * version which is really broken. */ + * undefine basename() since libgen.h defines it as a macro to the POSIX + * version which is really broken. We prefer GNU basename(). */ #include #undef basename -#include "util.h" -#include "strv.h" -#include "memfd-util.h" -#include "capability.h" -#include "fileio.h" - +#include "alloc-util.h" +#include "bus-bloom.h" #include "bus-internal.h" -#include "bus-message.h" #include "bus-kernel.h" -#include "bus-bloom.h" -#include "bus-util.h" #include "bus-label.h" +#include "bus-message.h" +#include "bus-util.h" +#include "capability-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "formats-util.h" +#include "memfd-util.h" +#include "parse-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t)) @@ -167,6 +172,27 @@ static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, bloom_add_prefixes(data, size, n_hash, buf, t, '/'); } +static void add_bloom_arg_has(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) { + char buf[sizeof("arg")-1 + 2 + sizeof("-has")]; + char *e; + + assert(data); + assert(size > 0); + assert(i < 64); + assert(t); + + e = stpcpy(buf, "arg"); + if (i < 10) + *(e++) = '0' + (char) i; + else { + *(e++) = '0' + (char) (i / 10); + *(e++) = '0' + (char) (i % 10); + } + + strcpy(e, "-has"); + bloom_add_pair(data, size, n_hash, buf, t); +} + static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) { void *data; unsigned i; @@ -211,7 +237,9 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter return r; add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); - } if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) { + } + + if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) { /* As well as array of simple strings of any kinds */ r = sd_bus_message_enter_container(m, type, contents); @@ -219,7 +247,7 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter return r; while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0) - add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); + add_bloom_arg_has(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); if (r < 0) return r; @@ -497,7 +525,6 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { footer, footer_size, n_bytes, fds, n_fds, - NULL, seclabel, 0, &m); if (r < 0) return r; @@ -594,6 +621,14 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask; } + if (d->pids.ppid > 0) { + m->creds.ppid = (pid_t) d->pids.ppid; + m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask; + } else if (d->pids.pid == 1) { + m->creds.ppid = 0; + m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask; + } + break; case KDBUS_ITEM_CREDS: @@ -680,15 +715,11 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { break; case KDBUS_ITEM_AUDIT: - if ((uint32_t) d->audit.sessionid != (uint32_t) -1) { - m->creds.audit_session_id = (uint32_t) d->audit.sessionid; - m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask; - } + m->creds.audit_session_id = (uint32_t) d->audit.sessionid; + m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask; - if ((uid_t) d->audit.loginuid != UID_INVALID) { - m->creds.audit_login_uid = (uid_t) d->audit.loginuid; - m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask; - } + m->creds.audit_login_uid = (uid_t) d->audit.loginuid; + m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask; break; case KDBUS_ITEM_CAPS: @@ -770,6 +801,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { case KDBUS_ITEM_FDS: case KDBUS_ITEM_SECLABEL: + case KDBUS_ITEM_BLOOM_FILTER: break; default: @@ -957,8 +989,16 @@ int bus_kernel_take_fd(sd_bus *b) { } r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello); - if (r < 0) + if (r < 0) { + if (errno == ENOTTY) + /* If the ioctl is not supported we assume that the + * API version changed in a major incompatible way, + * let's indicate an API incompatibility in this + * case. */ + return -ESOCKTNOSUPPORT; + return -errno; + } if (!b->kdbus_buffer) { b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0); @@ -972,7 +1012,7 @@ int bus_kernel_take_fd(sd_bus *b) { /* The higher 32bit of the bus_flags fields are considered * 'incompatible flags'. Refuse them all for now. */ if (hello->bus_flags > 0xFFFFFFFFULL) { - r = -EOPNOTSUPP; + r = -ESOCKTNOSUPPORT; goto fail; } @@ -1320,8 +1360,7 @@ static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) { KDBUS_ITEM_FOREACH(d, k, items) { if (d->type == KDBUS_ITEM_TIMESTAMP) ts = &d->timestamp; - - if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) { + else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) { if (found) return -EBADMSG; found = d; @@ -1373,15 +1412,16 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { r = 0; } - } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) + if (r <= 0) + close_kdbus_msg(bus, k); + } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) { r = bus_kernel_translate_message(bus, k); - else { + close_kdbus_msg(bus, k); + } else { log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type); r = 0; - } - - if (r <= 0) close_kdbus_msg(bus, k); + } return r < 0 ? r : 1; } @@ -1397,12 +1437,12 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al if (!bus || !bus->is_kernel) return -EOPNOTSUPP; - assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0); + assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0); if (bus->n_memfd_cache <= 0) { int r; - assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0); + assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0); r = memfd_new(bus->description); if (r < 0) @@ -1424,7 +1464,7 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al *allocated = c->allocated; fd = c->fd; - assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0); + assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0); return fd; } @@ -1448,10 +1488,10 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, si return; } - assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0); + assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0); if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) { - assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0); + assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0); close_and_munmap(fd, address, mapped); return; @@ -1471,7 +1511,7 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, si c->allocated = allocated; } - assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0); + assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0); } void bus_kernel_flush_memfd(sd_bus *b) { @@ -1505,7 +1545,7 @@ uint64_t attach_flags_to_kdbus(uint64_t mask) { SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) m |= KDBUS_ATTACH_CREDS; - if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID)) + if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID)) m |= KDBUS_ATTACH_PIDS; if (mask & SD_BUS_CREDS_COMM) @@ -1544,6 +1584,8 @@ uint64_t attach_flags_to_kdbus(uint64_t mask) { return m; } +/// UNNEEDED by elogind +#if 0 int bus_kernel_create_bus(const char *name, bool world, char **s) { struct kdbus_cmd *make; struct kdbus_item *n; @@ -1561,7 +1603,6 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { make = alloca0_align(offsetof(struct kdbus_cmd, items) + ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) + ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) + - ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) + ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1), 8); @@ -1580,14 +1621,6 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { make->size += ALIGN8(n->size); - /* The busses we create make no restrictions on what metadata - * peers can read from incoming messages. */ - n = KDBUS_ITEM_NEXT(n); - n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV; - n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t); - n->data64[0] = _KDBUS_ATTACH_ANY; - make->size += ALIGN8(n->size); - /* Provide all metadata via bus-owner queries */ n = KDBUS_ITEM_NEXT(n); n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND; @@ -1606,6 +1639,11 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) { safe_close(fd); + + /* Major API change? then the ioctls got shuffled around. */ + if (errno == ENOTTY) + return -ESOCKTNOSUPPORT; + return -errno; } @@ -1623,6 +1661,7 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { return fd; } +#endif // 0 int bus_kernel_open_bus_fd(const char *bus, char **path) { char *p; @@ -1656,6 +1695,8 @@ int bus_kernel_open_bus_fd(const char *bus, char **path) { return fd; } +/// UNNEEDED by elogind +#if 0 int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) { _cleanup_free_ char *path = NULL; struct kdbus_cmd *make; @@ -1699,6 +1740,7 @@ int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char * return fd; } +#endif // 0 int bus_kernel_try_close(sd_bus *bus) { struct kdbus_cmd byebye = { .size = sizeof(byebye) }; @@ -1712,6 +1754,8 @@ int bus_kernel_try_close(sd_bus *bus) { return 0; } +/// UNNEEDED by elogind +#if 0 int bus_kernel_drop_one(int fd) { struct kdbus_cmd_recv recv = { .size = sizeof(recv), @@ -1725,6 +1769,7 @@ int bus_kernel_drop_one(int fd) { return 0; } +#endif // 0 int bus_kernel_realize_attach_flags(sd_bus *bus) { struct kdbus_cmd *update; @@ -1752,32 +1797,6 @@ int bus_kernel_realize_attach_flags(sd_bus *bus) { return 0; } -int bus_kernel_fix_attach_mask(void) { - _cleanup_free_ char *mask = NULL; - uint64_t m = (uint64_t) -1; - char buf[2+16+2]; - int r; - - /* By default we don't want any kdbus metadata fields to be - * suppressed, hence we reset the kernel mask for it to - * (uint64_t) -1. If the module argument was overwritten by - * the kernel cmdline, we leave it as is. */ - - r = get_proc_cmdline_key("kdbus.attach_flags_mask=", &mask); - if (r < 0) - return log_warning_errno(r, "Failed to read kernel command line: %m"); - - if (r == 0) { - sprintf(buf, "0x%" PRIx64 "\n", m); - r = write_string_file("/sys/module/kdbus/parameters/attach_flags_mask", buf); - if (r < 0) - return log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to write kdbus attach mask: %m"); - } - - return 0; -} - int bus_kernel_get_bus_name(sd_bus *bus, char **name) { struct kdbus_cmd_info cmd = { .size = sizeof(struct kdbus_cmd_info),