mirror of
https://github.com/systemd/systemd.git
synced 2025-01-26 14:04:03 +03:00
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
This commit is contained in:
commit
3907b25638
@ -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)
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
127
src/libsystemd/sd-bus/test-bus-peersockaddr.c
Normal file
127
src/libsystemd/sd-bus/test-bus-peersockaddr.c
Normal file
@ -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);
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user