X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fsd-bus.c;h=5e66a31162611ac2d7ae988840aa55950a458320;hb=45fbe937d7ca8d0da9ea276d57bc70ebd41c285e;hp=08ab202baf8301b1eca4c280d2fa52a1e5ba802a;hpb=f54514f3542db9b1f1a6f7546472718ce0d02aae;p=elogind.git diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 08ab202ba..5e66a3116 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "util.h" #include "macro.h" @@ -64,6 +66,9 @@ static void bus_free(sd_bus *b) { bus_close_fds(b); + if (b->kdbus_buffer) + munmap(b->kdbus_buffer, KDBUS_POOL_SIZE); + free(b->rbuffer); free(b->unique_name); free(b->auth_buffer); @@ -102,6 +107,8 @@ static void bus_free(sd_bus *b) { bus_kernel_flush_memfd(b); + assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0); + free(b); } @@ -119,6 +126,9 @@ int sd_bus_new(sd_bus **ret) { r->input_fd = r->output_fd = -1; r->message_version = 1; r->negotiate_fds = true; + r->original_pid = getpid(); + + assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0); /* We guarantee that wqueue always has space for at least one * entry */ @@ -141,6 +151,8 @@ int sd_bus_set_address(sd_bus *bus, const char *address) { return -EPERM; if (!address) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; a = strdup(address); if (!a) @@ -161,6 +173,8 @@ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) { return -EINVAL; if (output_fd < 0) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; bus->input_fd = input_fd; bus->output_fd = output_fd; @@ -178,6 +192,8 @@ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) { return -EINVAL; if (strv_isempty(argv)) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; p = strdup(path); if (!p) @@ -203,6 +219,8 @@ int sd_bus_set_bus_client(sd_bus *bus, int b) { return -EINVAL; if (bus->state != BUS_UNSET) return -EPERM; + if (bus_pid_changed(bus)) + return -ECHILD; bus->bus_client = !!b; return 0; @@ -213,6 +231,8 @@ int sd_bus_set_negotiate_fds(sd_bus *bus, int b) { return -EINVAL; if (bus->state != BUS_UNSET) return -EPERM; + if (bus_pid_changed(bus)) + return -ECHILD; bus->negotiate_fds = !!b; return 0; @@ -225,6 +245,8 @@ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) { return -EINVAL; if (bus->state != BUS_UNSET) return -EPERM; + if (bus_pid_changed(bus)) + return -ECHILD; bus->is_server = !!b; bus->server_id = server_id; @@ -236,6 +258,8 @@ int sd_bus_set_anonymous(sd_bus *bus, int b) { return -EINVAL; if (bus->state != BUS_UNSET) return -EPERM; + if (bus_pid_changed(bus)) + return -ECHILD; bus->anonymous_auth = !!b; return 0; @@ -824,6 +848,8 @@ int sd_bus_start(sd_bus *bus) { return -EINVAL; if (bus->state != BUS_UNSET) return -EPERM; + if (bus_pid_changed(bus)) + return -ECHILD; bus->state = BUS_OPENING; @@ -933,8 +959,9 @@ fail: void sd_bus_close(sd_bus *bus) { if (!bus) return; - - if (bus->state != BUS_CLOSED) + if (bus->state == BUS_CLOSED) + return; + if (bus_pid_changed(bus)) return; bus->state = BUS_CLOSED; @@ -971,6 +998,8 @@ sd_bus *sd_bus_unref(sd_bus *bus) { int sd_bus_is_open(sd_bus *bus) { if (!bus) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; return BUS_IS_OPEN(bus->state); } @@ -982,6 +1011,8 @@ int sd_bus_can_send(sd_bus *bus, char type) { return -EINVAL; if (bus->state == BUS_UNSET) return -ENOTCONN; + if (bus_pid_changed(bus)) + return -ECHILD; if (type == SD_BUS_TYPE_UNIX_FD) { if (!bus->negotiate_fds) @@ -1004,6 +1035,8 @@ int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) { return -EINVAL; if (!server_id) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; r = bus_ensure_running(bus); if (r < 0) @@ -1114,6 +1147,8 @@ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) { return -ENOTCONN; if (!m) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; if (m->n_fds > 0) { r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD); @@ -1231,6 +1266,8 @@ int sd_bus_send_with_reply( return -EINVAL; if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func); if (r < 0) @@ -1286,6 +1323,8 @@ int sd_bus_send_with_reply_cancel(sd_bus *bus, uint64_t serial) { return -EINVAL; if (serial == 0) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; c = hashmap_remove(bus->reply_callbacks, &serial); if (!c) @@ -1347,6 +1386,8 @@ int sd_bus_send_with_reply_and_block( return -EINVAL; if (bus_error_is_dirty(error)) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; r = bus_ensure_running(bus); if (r < 0) @@ -1457,6 +1498,8 @@ int sd_bus_get_fd(sd_bus *bus) { return -ENOTCONN; if (bus->input_fd != bus->output_fd) return -EPERM; + if (bus_pid_changed(bus)) + return -ECHILD; return bus->input_fd; } @@ -1468,6 +1511,8 @@ int sd_bus_get_events(sd_bus *bus) { return -EINVAL; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; + if (bus_pid_changed(bus)) + return -ECHILD; if (bus->state == BUS_OPENING) flags |= POLLOUT; @@ -1497,6 +1542,8 @@ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) { return -EINVAL; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; + if (bus_pid_changed(bus)) + return -ECHILD; if (bus->state == BUS_AUTHENTICATING) { *timeout_usec = bus->auth_timeout; @@ -1992,6 +2039,8 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) { if (!bus) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; /* We don't allow recursively invoking sd_bus_process(). */ if (bus->processing) @@ -2089,6 +2138,9 @@ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) { return -EINVAL; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; + if (bus_pid_changed(bus)) + return -ECHILD; + if (bus->rqueue_size > 0) return 0; @@ -2102,6 +2154,8 @@ int sd_bus_flush(sd_bus *bus) { return -EINVAL; if (!BUS_IS_OPEN(bus->state)) return -ENOTCONN; + if (bus_pid_changed(bus)) + return -ECHILD; r = bus_ensure_running(bus); if (r < 0) @@ -2131,6 +2185,8 @@ int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *user return -EINVAL; if (!callback) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; f = new0(struct filter_callback, 1); if (!f) @@ -2150,6 +2206,8 @@ int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *u return -EINVAL; if (!callback) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; LIST_FOREACH(callbacks, f, bus->filter_callbacks) { if (f->callback == callback && f->userdata == userdata) { @@ -2179,6 +2237,8 @@ static int bus_add_object( return -EINVAL; if (!callback) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; r = hashmap_ensure_allocated(&bus->object_callbacks, string_hash_func, string_compare_func); if (r < 0) @@ -2224,6 +2284,8 @@ static int bus_remove_object( return -EINVAL; if (!callback) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; c = hashmap_get(bus->object_callbacks, path); if (!c) @@ -2264,6 +2326,8 @@ int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t ca return -EINVAL; if (!match) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; if (bus->bus_client) { r = bus_add_match_internal(bus, match); @@ -2291,6 +2355,8 @@ int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t return -EINVAL; if (!match) return -EINVAL; + if (bus_pid_changed(bus)) + return -ECHILD; if (bus->bus_client) r = bus_remove_match_internal(bus, match); @@ -2318,6 +2384,10 @@ int sd_bus_emit_signal( if (!bus) return -EINVAL; + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + if (bus_pid_changed(bus)) + return -ECHILD; r = sd_bus_message_new_signal(bus, path, interface, member, &m); if (r < 0) @@ -2348,6 +2418,10 @@ int sd_bus_call_method( if (!bus) return -EINVAL; + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + if (bus_pid_changed(bus)) + return -ECHILD; r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m); if (r < 0) @@ -2379,6 +2453,10 @@ int sd_bus_reply_method_return( return -EPERM; if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL) return -EINVAL; + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + if (bus_pid_changed(bus)) + return -ECHILD; if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; @@ -2414,6 +2492,10 @@ int sd_bus_reply_method_error( return -EINVAL; if (!sd_bus_error_is_set(e)) return -EINVAL; + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + if (bus_pid_changed(bus)) + return -ECHILD; if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; @@ -2424,3 +2506,12 @@ int sd_bus_reply_method_error( return sd_bus_send(bus, m, NULL); } + +bool bus_pid_changed(sd_bus *bus) { + assert(bus); + + /* We don't support people creating a bus connection and + * keeping it around over a fork(). Let's complain. */ + + return bus->original_pid != getpid(); +}