From f8ecc2c00df7bd810557f3056ec12f6a0730812d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Dec 2020 13:16:39 +0100 Subject: [PATCH] sd-bus: make credential acquisition more graceful MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far when asked for augmented bus credentials and the process was already gone we'd fail fatally. Let's make this graceful instead, and never allow augmenting fail due to PID having vanished — unless the augmenting is the explicit and only purpose of the requested operation. This should be safe as clients have to explicitly query the acquired creds anyway and handle if they couldn't be acquired. Moreover we already handle permission problems gracefully, thus clients must be ready to deal with missing creds. This is useful to make selinux authorization work for short-lived client proceses. PReviously we'd augment creds to have more info to log about (the selinux decision would not be based on augmented data however, because that'd be unsafe), and would fail if we couldn't get it. Now, we'll try to acquire the data, but if we cannot acquire it, we'll still do the selinux check, except that logging will be more limited. --- src/libsystemd/sd-bus/bus-control.c | 4 ++-- src/libsystemd/sd-bus/bus-convenience.c | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index a63937e1ce..3ee22c9638 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -713,7 +713,7 @@ _public_ int sd_bus_get_name_creds( } r = bus_creds_add_more(c, mask, pid, 0); - if (r < 0) + if (r < 0 && r != -ESRCH) /* Return the error, but ignore ESRCH which just means the process is already gone */ return r; } @@ -788,7 +788,7 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r } r = bus_creds_add_more(c, mask, pid, 0); - if (r < 0) + if (r < 0 && r != -ESRCH) /* If the process vanished, then don't complain, just return what we got */ return r; *ret = TAKE_PTR(c); diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c index 4bf228b436..ea2fd8935b 100644 --- a/src/libsystemd/sd-bus/bus-convenience.c +++ b/src/libsystemd/sd-bus/bus-convenience.c @@ -603,8 +603,9 @@ _public_ int sd_bus_set_property( return r; } -_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) { +_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **ret) { sd_bus_creds *c; + int r; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); @@ -618,7 +619,7 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b /* All data we need? */ if (c && (mask & ~c->mask) == 0) { - *creds = sd_bus_creds_ref(c); + *ret = sd_bus_creds_ref(c); return 0; } @@ -629,15 +630,22 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b if (call->sender) /* There's a sender, but the creds are missing. */ - return sd_bus_get_name_creds(call->bus, call->sender, mask, creds); + return sd_bus_get_name_creds(call->bus, call->sender, mask, ret); else /* There's no sender. For direct connections * the credentials of the AF_UNIX peer matter, * which may be queried via sd_bus_get_owner_creds(). */ - return sd_bus_get_owner_creds(call->bus, mask, creds); + return sd_bus_get_owner_creds(call->bus, mask, ret); } - return bus_creds_extend_by_pid(c, mask, creds); + r = bus_creds_extend_by_pid(c, mask, ret); + if (r == -ESRCH) { + /* Process doesn't exist anymore? propagate the few things we have */ + *ret = sd_bus_creds_ref(c); + return 0; + } + + return r; } _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {