diff options
Diffstat (limited to 'src/libsystemd/sd-bus')
-rw-r--r-- | src/libsystemd/sd-bus/bus-control.c | 78 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-internal.h | 2 | ||||
-rw-r--r-- | 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 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 11f4aa9669..741d54cabd 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) { |