From 4b7604af317c157c7a1db583959cb9ca6976925f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 May 2023 20:01:05 +0200 Subject: [PATCH 1/7] test-bus-chat: modernize a few things --- src/libsystemd/sd-bus/test-bus-chat.c | 156 +++++++++----------------- 1 file changed, 54 insertions(+), 102 deletions(-) diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c index 8e66919b463..7abe129186b 100644 --- a/src/libsystemd/sd-bus/test-bus-chat.c +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -46,31 +46,25 @@ static int object_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_ return 0; } -static int server_init(sd_bus **_bus) { - sd_bus *bus = NULL; +static int server_init(sd_bus **ret_bus) { + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + const char *unique, *desc; sd_id128_t id; int r; - const char *unique, *desc; - assert_se(_bus); + assert_se(ret_bus); r = sd_bus_open_user_with_description(&bus, "my bus!"); - if (r < 0) { - log_error_errno(r, "Failed to connect to user bus: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to connect to user bus: %m"); r = sd_bus_get_bus_id(bus, &id); - if (r < 0) { - log_error_errno(r, "Failed to get server ID: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to get server ID: %m"); r = sd_bus_get_unique_name(bus, &unique); - if (r < 0) { - log_error_errno(r, "Failed to get unique name: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to get unique name: %m"); assert_se(sd_bus_get_description(bus, &desc) >= 0); assert_se(streq(desc, "my bus!")); @@ -80,48 +74,35 @@ static int server_init(sd_bus **_bus) { log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h')); r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0); - if (r < 0) { - log_error_errno(r, "Failed to acquire name: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to acquire name: %m"); r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL); - if (r < 0) { - log_error_errno(r, "Failed to add object: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to add object: %m"); r = sd_bus_match_signal(bus, NULL, NULL, NULL, "foo.bar", "Notify", match_callback, NULL); - if (r < 0) { - log_error_errno(r, "Failed to request match: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to request match: %m"); r = sd_bus_match_signal(bus, NULL, NULL, NULL, "foo.bar", "NotifyTo", match_callback, NULL); - if (r < 0) { - log_error_errno(r, "Failed to request match: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to request match: %m"); r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL); - if (r < 0) { - log_error_errno(r, "Failed to add match: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to add match: %m"); bus_match_dump(stdout, &bus->match_callbacks, 0); - *_bus = bus; + *ret_bus = TAKE_PTR(bus); return 0; - -fail: - sd_bus_unref(bus); - return r; } -static int server(sd_bus *bus) { - int r; +static int server(sd_bus *_bus) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = ASSERT_PTR(_bus); bool client1_gone = false, client2_gone = false; + int r; while (!client1_gone || !client2_gone) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; @@ -129,30 +110,26 @@ static int server(sd_bus *bus) { const char *label = NULL; r = sd_bus_process(bus, &m); - if (r < 0) { - log_error_errno(r, "Failed to process requests: %m"); - goto fail; - } - + if (r < 0) + return log_error_errno(r, "Failed to process requests: %m"); if (r == 0) { r = sd_bus_wait(bus, UINT64_MAX); - if (r < 0) { - log_error_errno(r, "Failed to wait: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to wait: %m"); continue; } - if (!m) continue; - sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid); - sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label); + (void) sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid); + (void) sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label); + log_info("Got message! member=%s pid="PID_FMT" label=%s", strna(sd_bus_message_get_member(m)), pid, strna(label)); + /* sd_bus_message_dump(m); */ /* sd_bus_message_rewind(m, true); */ @@ -161,40 +138,31 @@ static int server(sd_bus *bus) { _cleanup_free_ char *lowercase = NULL; r = sd_bus_message_read(m, "s", &hello); - if (r < 0) { - log_error_errno(r, "Failed to get parameter: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to get parameter: %m"); lowercase = strdup(hello); - if (!lowercase) { - r = log_oom(); - goto fail; - } + if (!lowercase) + return log_oom(); ascii_strlower(lowercase); r = sd_bus_reply_method_return(m, "s", lowercase); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to send reply: %m"); + } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) { r = sd_bus_reply_method_return(m, NULL); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to send reply: %m"); client1_gone = true; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) { r = sd_bus_reply_method_return(m, NULL); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to send reply: %m"); client2_gone = true; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) { @@ -202,56 +170,40 @@ static int server(sd_bus *bus) { sleep(1); r = sd_bus_reply_method_return(m, NULL); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to send reply: %m"); } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) { int fd; static const char x = 'X'; r = sd_bus_message_read(m, "h", &fd); - if (r < 0) { - log_error_errno(r, "Failed to get parameter: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to get parameter: %m"); log_info("Received fd=%d", fd); if (write(fd, &x, 1) < 0) { - log_error_errno(errno, "Failed to write to fd: %m"); + r = log_error_errno(errno, "Failed to write to fd: %m"); safe_close(fd); - goto fail; + return r; } r = sd_bus_reply_method_return(m, NULL); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to send reply: %m"); } else if (sd_bus_message_is_method_call(m, NULL, NULL)) { r = sd_bus_reply_method_error( m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")); - if (r < 0) { - log_error_errno(r, "Failed to send reply: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to send reply: %m"); } } - r = 0; - -fail: - if (bus) { - sd_bus_flush(bus); - sd_bus_unref(bus); - } - - return r; + return 0; } static void* client1(void *p) { From f7794e423ae79325bdbf7b3637b7cb7a1a57e62e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 May 2023 21:47:43 +0200 Subject: [PATCH 2/7] test-bus-server: minor modernizations --- src/libsystemd/sd-bus/test-bus-server.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c index ab4045ee15b..5024c1d4f5c 100644 --- a/src/libsystemd/sd-bus/test-bus-server.c +++ b/src/libsystemd/sd-bus/test-bus-server.c @@ -22,8 +22,8 @@ struct context { }; static void *server(void *p) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; struct context *c = p; - sd_bus *bus = NULL; sd_id128_t id; bool quit = false; int r; @@ -97,11 +97,6 @@ static void *server(void *p) { r = 0; fail: - if (bus) { - sd_bus_flush(bus); - sd_bus_unref(bus); - } - return INT_TO_PTR(r); } From a0cb33581630a54c89d088d36eb3bf6cf7459cd7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 May 2023 21:35:19 +0200 Subject: [PATCH 3/7] sd-bus: bind outgoing AF_UNIX sockets to abstract addresses conveying client comm + bus description string Let's pass some additional meta information along bus connections without actually altering the communication protocol. Pass the client comm and client description string of the bus via including it in the abstract namespace client socket address we connect to. This is purely informational (and entirely user controlled), but has the benefit that servers can make use of the information if they want, but really don't have to. It works entirely transparently. This takes inspiration from how we convey similar information via credential socket connections. --- src/libsystemd/sd-bus/bus-socket.c | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index ceda20f289e..11f4aa9669d 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -22,6 +22,7 @@ #include "memory-util.h" #include "path-util.h" #include "process-util.h" +#include "random-util.h" #include "signal-util.h" #include "stdio-util.h" #include "string-util.h" @@ -889,6 +890,50 @@ fail: return r; } +static int bind_description(sd_bus *b, int fd, int family) { + _cleanup_free_ char *bind_name = NULL, *comm = NULL; + union sockaddr_union bsa; + const char *d = NULL; + int r; + + assert(b); + assert(fd >= 0); + + /* If this is an AF_UNIX socket, let's set our client's socket address to carry the description + * string for this bus connection. This is useful for debugging things, as the connection name is + * visible in various socket-related tools, and can even be queried by the server side. */ + + if (family != AF_UNIX) + return 0; + + (void) sd_bus_get_description(b, &d); + + /* Generate a recognizable source address in the abstract namespace. We'll include: + * - a random 64bit value (to avoid collisions) + * - our "comm" process name (suppressed if contains "/" to avoid parsing issues) + * - the description string of the bus connection. */ + (void) get_process_comm(0, &comm); + if (comm && strchr(comm, '/')) + comm = mfree(comm); + + if (!d && !comm) /* skip if we don't have either field, rely on kernel autobind instead */ + return 0; + + if (asprintf(&bind_name, "@%" PRIx64 "/bus/%s/%s", random_u64(), strempty(comm), strempty(d)) < 0) + return -ENOMEM; + + strshorten(bind_name, sizeof_field(struct sockaddr_un, sun_path)); + + r = sockaddr_un_set_path(&bsa.un, bind_name); + if (r < 0) + return r; + + if (bind(fd, &bsa.sa, r) < 0) + return -errno; + + return 0; +} + int bus_socket_connect(sd_bus *b) { bool inotify_done = false; int r; @@ -911,6 +956,10 @@ int bus_socket_connect(sd_bus *b) { if (b->input_fd < 0) return -errno; + r = bind_description(b, b->input_fd, b->sockaddr.sa.sa_family); + if (r < 0) + return r; + b->input_fd = fd_move_above_stdio(b->input_fd); b->output_fd = b->input_fd; From c32f9648cc058c96b2ab927b73af3fa28f7c69f6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 May 2023 21:43:57 +0200 Subject: [PATCH 4/7] sd-bus: use the new information in the client's sockaddr in the creds structure Now that clients might convey comm/description strings via the sockaddr, let's actually use them on the other side, read the data via getpeername() parse it, and include it in the "owner" creds (which is how we call the peer's creds). --- src/libsystemd/sd-bus/bus-control.c | 78 +++++++++++++++++++++++++++- src/libsystemd/sd-bus/bus-internal.h | 2 + src/libsystemd/sd-bus/bus-socket.c | 11 ++++ 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index 864acd73ac1..287cde6d419 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -722,9 +722,51 @@ _public_ int sd_bus_get_name_creds( return 0; } +static int parse_sockaddr_string(const char *t, char **ret_comm, char **ret_description) { + _cleanup_free_ char *comm = NULL, *description = NULL; + const char *e, *sl; + + assert(t); + assert(ret_comm); + assert(ret_description); + + e = strstrafter(t, "/bus/"); + if (!e) { + log_debug("Didn't find /bus/ substring in peer socket address, ignoring."); + goto not_found; + } + + sl = strchr(e, '/'); + if (!sl) { + log_debug("Didn't find / substring after /bus/ in peer socket address, ignoring."); + goto not_found; + } + + if (sl - e > 0) { + comm = strndup(e, sl - e); + if (!comm) + return -ENOMEM; + } + + sl++; + if (!isempty(sl)) { + description = strdup(sl); + if (!description) + return -ENOMEM; + } + + *ret_comm = TAKE_PTR(comm); + *ret_description = TAKE_PTR(description); + return 0; + +not_found: + *ret_comm = *ret_description = NULL; + return 0; +} + _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; - bool do_label, do_groups; + bool do_label, do_groups, do_sockaddr_peer; pid_t pid = 0; int r; @@ -742,9 +784,12 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT); do_groups = bus->n_groups != SIZE_MAX && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS); + do_sockaddr_peer = bus->sockaddr_size_peer >= offsetof(struct sockaddr_un, sun_path) + 1 && + bus->sockaddr_peer.sa.sa_family == AF_UNIX && + bus->sockaddr_peer.un.sun_path[0] == 0; /* Avoid allocating anything if we have no chance of returning useful data */ - if (!bus->ucred_valid && !do_label && !do_groups) + if (!bus->ucred_valid && !do_label && !do_groups && !do_sockaddr_peer) return -ENODATA; c = bus_creds_new(); @@ -786,6 +831,35 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; } + if (do_sockaddr_peer) { + _cleanup_free_ char *t = NULL; + + assert(bus->sockaddr_size_peer >= offsetof(struct sockaddr_un, sun_path) + 1); + assert(bus->sockaddr_peer.sa.sa_family == AF_UNIX); + assert(bus->sockaddr_peer.un.sun_path[0] == 0); + + /* So this is an abstract namespace socket, good. Now let's find the data we are interested in */ + r = make_cstring(bus->sockaddr_peer.un.sun_path + 1, + bus->sockaddr_size_peer - offsetof(struct sockaddr_un, sun_path) - 1, + MAKE_CSTRING_ALLOW_TRAILING_NUL, + &t); + if (r == -ENOMEM) + return r; + if (r < 0) + log_debug_errno(r, "Can't extract string from peer socket address, ignoring: %m"); + else { + r = parse_sockaddr_string(t, &c->comm, &c->description); + if (r < 0) + return r; + + if (c->comm) + c->mask |= SD_BUS_CREDS_COMM & mask; + + if (c->description) + c->mask |= SD_BUS_CREDS_DESCRIPTION & mask; + } + } + r = bus_creds_add_more(c, mask, pid, 0); if (r < 0 && r != -ESRCH) /* If the process vanished, then don't complain, just return what we got */ return r; diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 0e44897e0e1..1cf6974bff9 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -267,6 +267,8 @@ struct sd_bus { char *label; gid_t *groups; size_t n_groups; + union sockaddr_union sockaddr_peer; + socklen_t sockaddr_size_peer; uint64_t creds_mask; diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 11f4aa9669d..741d54cabdf 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -652,6 +652,17 @@ static void bus_get_peercred(sd_bus *b) { b->n_groups = (size_t) r; else if (!IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT)) log_debug_errno(r, "Failed to determine peer's group list: %m"); + + /* Let's query the peers socket address, it might carry information such as the peer's comm or + * description string */ + zero(b->sockaddr_peer); + b->sockaddr_size_peer = 0; + + socklen_t l = sizeof(b->sockaddr_peer) - 1; /* Leave space for a NUL */ + if (getpeername(b->input_fd, &b->sockaddr_peer.sa, &l) < 0) + log_debug_errno(errno, "Failed to get peer's socket address, ignoring: %m"); + else + b->sockaddr_size_peer = l; } static int bus_socket_start_auth_client(sd_bus *b) { From b587194313cbad2fbd6a7e70cec860f0d0ed798c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 May 2023 21:47:02 +0200 Subject: [PATCH 5/7] test: add testcase for the new sockaddr metainfo logic --- src/libsystemd/meson.build | 4 + src/libsystemd/sd-bus/test-bus-peersockaddr.c | 127 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 src/libsystemd/sd-bus/test-bus-peersockaddr.c diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build index aa424970802..ee24240cd13 100644 --- a/src/libsystemd/meson.build +++ b/src/libsystemd/meson.build @@ -210,6 +210,10 @@ tests += [ 'sources' : files('sd-bus/test-bus-objects.c'), 'dependencies' : threads, }, + { + 'sources' : files('sd-bus/test-bus-peersockaddr.c'), + 'dependencies' : threads, + }, { 'sources' : files('sd-bus/test-bus-queue-ref-cycle.c'), 'dependencies' : threads, diff --git a/src/libsystemd/sd-bus/test-bus-peersockaddr.c b/src/libsystemd/sd-bus/test-bus-peersockaddr.c new file mode 100644 index 00000000000..8bab4296242 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-peersockaddr.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include + +#include "sd-bus.h" + +#include "fd-util.h" +#include "process-util.h" +#include "socket-util.h" +#include "tests.h" + +static void *server(void *p) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_close_ int listen_fd = PTR_TO_INT(p), fd = -EBADF; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; + _cleanup_free_ char *our_comm = NULL; + sd_id128_t id; + int r; + + assert_se(sd_id128_randomize(&id) >= 0); + + fd = accept4(listen_fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); + assert_se(fd >= 0); + + assert_se(sd_bus_new(&bus) >= 0); + assert_se(sd_bus_set_fd(bus, fd, fd) >= 0); + TAKE_FD(fd); + assert_se(sd_bus_set_server(bus, true, id) >= 0); + assert_se(sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION) >= 0); + + assert_se(sd_bus_start(bus) >= 0); + + assert_se(sd_bus_get_owner_creds(bus, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION, &c) >= 0); + + uid_t u; + assert_se(sd_bus_creds_get_euid(c, &u) >= 0); + assert_se(u == getuid()); + + gid_t g; + assert_se(sd_bus_creds_get_egid(c, &g) >= 0); + assert_se(g == getgid()); + + pid_t pid; + assert_se(sd_bus_creds_get_pid(c, &pid) >= 0); + assert_se(pid == getpid_cached()); + + const char *comm; + assert_se(sd_bus_creds_get_comm(c, &comm) >= 0); + assert_se(get_process_comm(0, &our_comm) >= 0); + assert_se(streq_ptr(comm, our_comm)); + + const char *description; + assert_se(sd_bus_creds_get_description(c, &description) >= 0); + assert_se(streq_ptr(description, "wuffwuff")); + + for (;;) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + r = sd_bus_process(bus, &m); + assert_se(r >= 0); + + if (r == 0) { + assert_se(sd_bus_wait(bus, UINT64_MAX) >= 0); + continue; + } + + if (sd_bus_message_is_method_call(m, "foo.foo", "Foo") > 0) { + assert_se(sd_bus_reply_method_return(m, "s", "bar") >= 0); + break; + } + } + + return NULL; +} + +static void* client(void *p) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *z; + + assert_se(sd_bus_new(&bus) >= 0); + assert_se(sd_bus_set_description(bus, "wuffwuff") >= 0); + assert_se(sd_bus_set_address(bus, p) >= 0); + assert_se(sd_bus_start(bus) >= 0); + + assert_se(sd_bus_call_method(bus, "foo.foo", "/foo", "foo.foo", "Foo", NULL, &reply, "s", "foo") >= 0); + + assert_se(sd_bus_message_read(reply, "s", &z) >= 0); + assert_se(streq_ptr(z, "bar")); + + return NULL; +} + +TEST(description) { + _cleanup_free_ char *a = NULL; + _cleanup_close_ int fd = -EBADF; + union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + }; + socklen_t salen; + pthread_t s, c; + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + assert_se(fd >= 0); + + assert_se(bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path)) >= 0); /* force auto-bind */ + + assert_se(listen(fd, 1) >= 0); + + salen = sizeof(sa); + assert_se(getsockname(fd, &sa.sa, &salen) >= 0); + assert_se(salen >= offsetof(struct sockaddr_un, sun_path)); + assert_se(sa.un.sun_path[0] == 0); + + assert_se(asprintf(&a, "unix:abstract=%s", sa.un.sun_path + 1) >= 0); + + assert_se(pthread_create(&s, NULL, server, INT_TO_PTR(fd)) == 0); + TAKE_FD(fd); + + assert_se(pthread_create(&c, NULL, client, a) == 0); + + assert_se(pthread_join(s, NULL) == 0); + assert_se(pthread_join(c, NULL) == 0); +} + +DEFINE_TEST_MAIN(LOG_INFO); From 7b674a9ee86dad21ba631b82c5b46938a3a587d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 May 2023 21:45:54 +0200 Subject: [PATCH 6/7] pid1: debug log client comm/description strings if available for incoming connections Very useful for debugging, to see which clients actually connect. --- src/core/dbus.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/core/dbus.c b/src/core/dbus.c index c41e1a6c746..7277696196e 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -684,7 +684,7 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void return 0; } - nfd = -EBADF; + TAKE_FD(nfd); r = bus_check_peercred(bus); if (r < 0) { @@ -703,7 +703,8 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void r = sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_PID|SD_BUS_CREDS_UID| SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS| - SD_BUS_CREDS_SELINUX_CONTEXT); + SD_BUS_CREDS_SELINUX_CONTEXT| + SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION); if (r < 0) { log_warning_errno(r, "Failed to enable credentials for new connection: %m"); return 0; @@ -721,6 +722,23 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void return 0; } + if (DEBUG_LOGGING) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; + const char *comm = NULL, *description = NULL; + pid_t pid = 0; + + r = sd_bus_get_owner_creds(bus, SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION, &c); + if (r < 0) + log_warning_errno(r, "Failed to get peer creds, ignoring: %m"); + else { + (void) sd_bus_creds_get_pid(c, &pid); + (void) sd_bus_creds_get_comm(c, &comm); + (void) sd_bus_creds_get_description(c, &description); + } + + log_debug("Accepting direct incoming connection from " PID_FMT " (%s) [%s]", pid, strna(comm), strna(description)); + } + r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL); if (r < 0) { log_warning_errno(r, "Failed to attach new connection bus to event loop: %m"); From acf493390ac601d90dc4ac188475635a5c327522 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 May 2023 21:33:56 +0200 Subject: [PATCH 7/7] busctl: set a description for the bus connection Unlike most other bus connections in our codebase this one is created manually and every setting set invididually. It hence does not have a description by default (as all automatic connections have). Set one explicitly. --- src/busctl/busctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index 90f20c05a16..820d27da20d 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -77,6 +77,8 @@ static int acquire_bus(bool set_monitor, sd_bus **ret) { if (r < 0) return log_error_errno(r, "Failed to allocate bus: %m"); + (void) sd_bus_set_description(bus, "busctl"); + if (set_monitor) { r = sd_bus_set_monitor(bus, true); if (r < 0)