summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-05-16 06:46:29 -0700
committerGitHub <noreply@github.com>2023-05-16 06:46:29 -0700
commit3907b2563855f42562643fd26e9dec515d4ef928 (patch)
treea841f95791531fdbfb1beeede5e3d932afc32d26 /src
parent93d4a200fbc1dd741a9971853a5efee7e537cc3e (diff)
parentacf493390ac601d90dc4ac188475635a5c327522 (diff)
downloadsystemd-3907b2563855f42562643fd26e9dec515d4ef928.tar.gz
Merge pull request #27573 from poettering/sd-bus-description
sd-bus: pass bus description (and comm name) to per via socket address binding on AF_UNIX
Diffstat (limited to 'src')
-rw-r--r--src/busctl/busctl.c2
-rw-r--r--src/core/dbus.c22
-rw-r--r--src/libsystemd/meson.build4
-rw-r--r--src/libsystemd/sd-bus/bus-control.c78
-rw-r--r--src/libsystemd/sd-bus/bus-internal.h2
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c60
-rw-r--r--src/libsystemd/sd-bus/test-bus-chat.c156
-rw-r--r--src/libsystemd/sd-bus/test-bus-peersockaddr.c127
-rw-r--r--src/libsystemd/sd-bus/test-bus-server.c7
9 files changed, 346 insertions, 112 deletions
diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c
index 90f20c05a1..820d27da20 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)
diff --git a/src/core/dbus.c b/src/core/dbus.c
index c41e1a6c74..7277696196 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");
diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build
index aa42497080..ee24240cd1 100644
--- a/src/libsystemd/meson.build
+++ b/src/libsystemd/meson.build
@@ -211,6 +211,10 @@ tests += [
'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/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index 864acd73ac..287cde6d41 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 0e44897e0e..1cf6974bff 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 ceda20f289..741d54cabd 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"
@@ -651,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) {
@@ -889,6 +901,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 +967,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;
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
index 8e66919b46..7abe129186 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) {
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 0000000000..8bab429624
--- /dev/null
+++ b/src/libsystemd/sd-bus/test-bus-peersockaddr.c
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <pthread.h>
+#include <unistd.h>
+
+#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);
diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c
index ab4045ee15..5024c1d4f5 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);
}