summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-bus
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd/sd-bus')
-rw-r--r--src/libsystemd/sd-bus/bus-convenience.c53
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c25
-rw-r--r--src/libsystemd/sd-bus/bus-util.c24
-rw-r--r--src/libsystemd/sd-bus/bus-util.h4
4 files changed, 65 insertions, 41 deletions
diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c
index c5b9cd4caa..f88836b884 100644
--- a/src/libsystemd/sd-bus/bus-convenience.c
+++ b/src/libsystemd/sd-bus/bus-convenience.c
@@ -472,3 +472,56 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
return bus_creds_extend_by_pid(c, mask, creds);
}
+
+_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
+ _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ uid_t our_uid;
+ int r;
+
+ assert_return(call, -EINVAL);
+ assert_return(call->sealed, -EPERM);
+ assert_return(call->bus, -EINVAL);
+ assert_return(!bus_pid_changed(call->bus), -ECHILD);
+
+ if (!BUS_IS_OPEN(call->bus->state))
+ return -ENOTCONN;
+
+ /* We only trust the effective capability set if this is
+ * kdbus. On classic dbus1 we cannot retrieve the value
+ * without races. Since this function is supposed to be useful
+ * for authentication decision we hence avoid requesting and
+ * using that information. */
+ if (call->bus->is_kernel && capability >= 0) {
+ r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_creds_has_effective_cap(creds, capability);
+ if (r > 0)
+ return 1;
+ } else {
+ r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID, &creds);
+ if (r < 0)
+ return r;
+ }
+
+ /* Now, check the UID, but only if the capability check wasn't
+ * sufficient */
+ our_uid = getuid();
+ if (our_uid != 0 || !call->bus->is_kernel || capability < 0) {
+ uid_t sender_uid;
+
+ r = sd_bus_creds_get_uid(creds, &sender_uid);
+ if (r >= 0) {
+ /* Sender has same UID as us, then let's grant access */
+ if (sender_uid == our_uid)
+ return 1;
+
+ /* Sender is root, we are not root. */
+ if (our_uid != 0 && sender_uid == 0)
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index dbb04e5ec6..78dab8048d 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -289,7 +289,6 @@ static int node_callbacks_run(
static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
uint64_t cap;
- uid_t uid;
int r;
assert(bus);
@@ -304,17 +303,6 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c,
if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED)
return 0;
- /* If we are not connected to kdbus we cannot retrieve the
- * effective capability set without race. Since we need this
- * for a security decision we cannot use racy data, hence
- * don't request it. */
- if (bus->is_kernel)
- r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
- else
- r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
- if (r < 0)
- return r;
-
/* Check have the caller has the requested capability
* set. Note that the flags value contains the capability
* number plus one, which we need to subtract here. We do this
@@ -328,16 +316,11 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c,
else
cap --;
- r = sd_bus_creds_has_effective_cap(creds, cap);
+ r = sd_bus_query_sender_privilege(m, cap);
+ if (r < 0)
+ return r;
if (r > 0)
- return 1;
-
- /* Caller has same UID as us, then let's grant access */
- r = sd_bus_creds_get_uid(creds, &uid);
- if (r >= 0) {
- if (uid == getuid())
- return 1;
- }
+ return 0;
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access to %s.%s() not permitted.", c->interface, c->member);
}
diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
index 37f5c4620c..65f1d17c9f 100644
--- a/src/libsystemd/sd-bus/bus-util.c
+++ b/src/libsystemd/sd-bus/bus-util.c
@@ -186,28 +186,22 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
int bus_verify_polkit(
sd_bus *bus,
sd_bus_message *m,
+ int capability,
const char *action,
bool interactive,
bool *_challenge,
sd_bus_error *e) {
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
- uid_t uid;
int r;
assert(bus);
assert(m);
assert(action);
- r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
+ r = sd_bus_query_sender_privilege(m, capability);
if (r < 0)
return r;
-
- r = sd_bus_creds_get_uid(creds, &uid);
- if (r < 0)
- return r;
-
- if (uid == 0)
+ if (r > 0)
return 1;
#ifdef ENABLE_POLKIT
@@ -325,6 +319,7 @@ int bus_verify_polkit_async(
sd_bus *bus,
Hashmap **registry,
sd_bus_message *m,
+ int capability,
const char *action,
bool interactive,
sd_bus_error *error,
@@ -336,8 +331,6 @@ int bus_verify_polkit_async(
AsyncPolkitQuery *q;
const char *sender;
#endif
- _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
- uid_t uid;
int r;
assert(bus);
@@ -383,15 +376,10 @@ int bus_verify_polkit_async(
}
#endif
- r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
+ r = sd_bus_query_sender_privilege(m, capability);
if (r < 0)
return r;
-
- r = sd_bus_creds_get_uid(creds, &uid);
- if (r < 0)
- return r;
-
- if (uid == 0)
+ if (r > 0)
return 1;
#ifdef ENABLE_POLKIT
diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h
index b3b52af24c..1ac46875b2 100644
--- a/src/libsystemd/sd-bus/bus-util.h
+++ b/src/libsystemd/sd-bus/bus-util.h
@@ -62,9 +62,9 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error);
int bus_check_peercred(sd_bus *c);
-int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, const char *action, bool interactive, bool *_challenge, sd_bus_error *e);
+int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, int capability, const char *action, bool interactive, bool *_challenge, sd_bus_error *e);
-int bus_verify_polkit_async(sd_bus *bus, Hashmap **registry, sd_bus_message *m, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata);
+int bus_verify_polkit_async(sd_bus *bus, Hashmap **registry, sd_bus_message *m, int capability, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata);
void bus_verify_polkit_async_registry_free(Hashmap *registry);
int bus_open_system_systemd(sd_bus **_bus);