[RFC PATCH 1/1] security: add SECURE_KEEP_FSUID to preserve fsuid/fsgid across execve

From: Igor Lubashev
Date: Thu Jun 13 2019 - 20:51:38 EST


Many kernel interfaces require real and/or effective root uid instead
of relying solely of capabilities. An executable that uses such
interfaces has to be set-uid-root or be executed by a thread with
effective root uid. Presently, fsuid and saved uid will reset to the
effective uid during execve. As a result, it is not possible to
execute a binary such that it has effective root uid but retains
fsuid/fsgid of the actual user. Retaining fsuid/fsgid of the actual
user could be required if the executable needs to access the
filesystem. It may also be desired from the security perspective of
delegating the minimal set of privileges.

Setting SECURE_KEEP_FSUID bit ensures that the current fsuid/fsgiud is
retained by execve.

Signed-off-by: Igor Lubashev <ilubashe@xxxxxxxxxx>
---
include/uapi/linux/securebits.h | 10 +++++++++-
security/commoncap.c | 9 +++++++--
2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/securebits.h b/include/uapi/linux/securebits.h
index d6d98877ff1a..6c20b2287d6f 100644
--- a/include/uapi/linux/securebits.h
+++ b/include/uapi/linux/securebits.h
@@ -52,10 +52,18 @@
#define SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED \
(issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE_LOCKED))

+/* When set, execve does not reset fsuid/fsgid to euid/egid */
+#define SECURE_KEEP_FSUID 8
+#define SECURE_KEEP_FSUID_LOCKED 9 /* make bit-8 immutable */
+
+#define SECBIT_KEEP_FSUID (issecure_mask(SECURE_KEEP_FSUID))
+#define SECBIT_KEEP_FSUID_LOCKED (issecure_mask(SECURE_KEEP_FSUID_LOCKED))
+
#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \
issecure_mask(SECURE_NO_SETUID_FIXUP) | \
issecure_mask(SECURE_KEEP_CAPS) | \
- issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE))
+ issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE) | \
+ issecure_mask(SECURE_KEEP_FSUID))
#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)

#endif /* _UAPI_LINUX_SECUREBITS_H */
diff --git a/security/commoncap.c b/security/commoncap.c
index c0b9664ee49e..e4de823a1d4e 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -847,8 +847,13 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
old->cap_permitted);
}

- new->suid = new->fsuid = new->euid;
- new->sgid = new->fsgid = new->egid;
+ new->suid = new->euid;
+ new->sgid = new->egid;
+
+ if (!issecure(SECURE_KEEP_FSUID)) {
+ new->fsuid = new->euid;
+ new->fsgid = new->egid;
+ }

/* File caps or setid cancels ambient. */
if (has_fcap || is_setid)
--
2.7.4