diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-04-21 00:58:08 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-04-21 00:58:56 +0200 |
commit | 0f51442056157cfec2efc52ddbff7392b0ff674a (patch) | |
tree | d806661843f62a79fea36f50657728b185146d05 | |
parent | 822d9b6e4c2f0dc1ebc606006dc52257f06850c5 (diff) |
sd-bus: when augmenting creds, remember which ones were augmented
Also, when we do permissions checks using creds, verify that we don't do
so based on augmented creds, as extra safety check.
-rw-r--r-- | src/core/selinux-access.c | 8 | ||||
-rw-r--r-- | src/libsystemd/libsystemd.sym.m4 | 1 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-convenience.c | 15 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-creds.c | 36 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-creds.h | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-util.c | 3 | ||||
-rw-r--r-- | src/systemd/sd-bus.h | 1 |
7 files changed, 52 insertions, 14 deletions
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c index 7058b7802d..5e9a4a5e02 100644 --- a/src/core/selinux-access.c +++ b/src/core/selinux-access.c @@ -222,6 +222,14 @@ int mac_selinux_generic_access_check( if (r < 0) goto finish; + /* The SELinux context is something we really should have + * gotten directly from the message or sender, and not be an + * augmented field. If it was augmented we cannot use it for + * authorization, since this is racy and vulnerable. Let's add + * an extra check, just in case, even though this really + * shouldn't be possible. */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_SELINUX_CONTEXT) == 0, -EPERM); + r = sd_bus_creds_get_selinux_context(creds, &scon); if (r < 0) goto finish; diff --git a/src/libsystemd/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym.m4 index 81f1122697..1b50486cfa 100644 --- a/src/libsystemd/libsystemd.sym.m4 +++ b/src/libsystemd/libsystemd.sym.m4 @@ -322,6 +322,7 @@ global: sd_bus_creds_ref; sd_bus_creds_unref; sd_bus_creds_get_mask; + sd_bus_creds_get_augmented_mask; sd_bus_creds_get_uid; sd_bus_creds_get_gid; sd_bus_creds_get_pid; diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c index 71ce757f70..28bc8d2818 100644 --- a/src/libsystemd/sd-bus/bus-convenience.c +++ b/src/libsystemd/sd-bus/bus-convenience.c @@ -499,10 +499,18 @@ _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) return -ENOTCONN; if (capability >= 0) { + r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds); if (r < 0) return r; + /* We cannot use augmented caps for authorization, + * since then data is acquired raceful from + * /proc. This can never actually happen, but let's + * better be safe than sorry, and do an extra check + * here. */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM); + /* Note that not even on kdbus we might have the caps * field, due to faked identities, or namespace * translation issues. */ @@ -523,6 +531,13 @@ _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) if (our_uid != 0 || !know_caps || capability < 0) { uid_t sender_uid; + /* We cannot use augmented uid/euid for authorization, + * since then data is acquired raceful from + * /proc. This can never actually happen, but let's + * better be safe than sorry, and do an extra check + * here. */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM); + /* Try to use the EUID, if we have it. */ r = sd_bus_creds_get_euid(creds, &sender_uid); if (r < 0) diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index 1183bbe6a1..b00b5308a8 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -131,6 +131,12 @@ _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) { return c->mask; } +_public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) { + assert_return(c, 0); + + return c->augmented; +} + sd_bus_creds* bus_creds_new(void) { sd_bus_creds *c; @@ -697,25 +703,25 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { if (!(mask & SD_BUS_CREDS_AUGMENT)) return 0; - missing = mask & ~c->mask; - if (missing == 0) - return 0; - /* Try to retrieve PID from creds if it wasn't passed to us */ if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID)) pid = c->pid; - if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID)) - tid = c->pid; - /* Without pid we cannot do much... */ if (pid <= 0) return 0; - if (pid > 0) { - c->pid = pid; - c->mask |= SD_BUS_CREDS_PID; - } + /* Try to retrieve TID from creds if it wasn't passed to us */ + if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID)) + tid = c->tid; + + /* Calculate what we shall and can add */ + missing = mask & ~(c->mask|SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_AUGMENT); + if (missing == 0) + return 0; + + c->pid = pid; + c->mask |= SD_BUS_CREDS_PID; if (tid > 0) { c->tid = tid; @@ -973,6 +979,8 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; } + c->augmented = missing & c->mask; + return 0; } @@ -1147,11 +1155,11 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) n->mask |= SD_BUS_CREDS_DESCRIPTION; } + n->augmented = c->augmented & n->mask; + /* Get more data */ - r = bus_creds_add_more(n, mask, - c->mask & SD_BUS_CREDS_PID ? c->pid : 0, - c->mask & SD_BUS_CREDS_TID ? c->tid : 0); + r = bus_creds_add_more(n, mask, 0, 0); if (r < 0) return r; diff --git a/src/libsystemd/sd-bus/bus-creds.h b/src/libsystemd/sd-bus/bus-creds.h index 5430e535f0..74062a583d 100644 --- a/src/libsystemd/sd-bus/bus-creds.h +++ b/src/libsystemd/sd-bus/bus-creds.h @@ -28,7 +28,9 @@ struct sd_bus_creds { bool allocated; unsigned n_ref; + uint64_t mask; + uint64_t augmented; uid_t uid; uid_t euid; diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c index ed366145d9..840878931f 100644 --- a/src/libsystemd/sd-bus/bus-util.c +++ b/src/libsystemd/sd-bus/bus-util.c @@ -206,6 +206,9 @@ static int check_good_user(sd_bus_message *m, uid_t good_user) { if (r < 0) return r; + /* Don't trust augmented credentials for authorization */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM); + r = sd_bus_creds_get_euid(creds, &sender_uid); if (r < 0) return r; diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index f6262a3ccf..f24cc08bd8 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -329,6 +329,7 @@ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t creds_mask sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c); sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c); uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c); +uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c); int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid); int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid); |