LSM: SafeSetID: refactor safesetid_security_capable()
authorJann Horn <jannh@google.com>
Wed, 10 Apr 2019 16:55:41 +0000 (09:55 -0700)
committerMicah Morton <mortonm@chromium.org>
Mon, 15 Jul 2019 15:06:58 +0000 (08:06 -0700)
At the moment, safesetid_security_capable() has two nested conditional
blocks, and one big comment for all the logic. Chop it up and reduce the
amount of indentation.

Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Micah Morton <mortonm@chromium.org>
security/safesetid/lsm.c

index 56e1b28..9db1c7a 100644 (file)
@@ -55,21 +55,32 @@ static int safesetid_security_capable(const struct cred *cred,
                                      int cap,
                                      unsigned int opts)
 {
-       if (cap == CAP_SETUID &&
-           setuid_policy_lookup(cred->uid, INVALID_UID) != SIDPOL_DEFAULT) {
-               if (!(opts & CAP_OPT_INSETID)) {
-                       /*
-                        * Deny if we're not in a set*uid() syscall to avoid
-                        * giving powers gated by CAP_SETUID that are related
-                        * to functionality other than calling set*uid() (e.g.
-                        * allowing user to set up userns uid mappings).
-                        */
-                       pr_warn("Operation requires CAP_SETUID, which is not available to UID %u for operations besides approved set*uid transitions\n",
-                               __kuid_val(cred->uid));
-                       return -1;
-               }
-       }
-       return 0;
+       /* We're only interested in CAP_SETUID. */
+       if (cap != CAP_SETUID)
+               return 0;
+
+       /*
+        * If CAP_SETUID is currently used for a set*uid() syscall, we want to
+        * let it go through here; the real security check happens later, in the
+        * task_fix_setuid hook.
+        */
+       if ((opts & CAP_OPT_INSETID) != 0)
+               return 0;
+
+       /*
+        * If no policy applies to this task, allow the use of CAP_SETUID for
+        * other purposes.
+        */
+       if (setuid_policy_lookup(cred->uid, INVALID_UID) == SIDPOL_DEFAULT)
+               return 0;
+
+       /*
+        * Reject use of CAP_SETUID for functionality other than calling
+        * set*uid() (e.g. setting up userns uid mappings).
+        */
+       pr_warn("Operation requires CAP_SETUID, which is not available to UID %u for operations besides approved set*uid transitions\n",
+               __kuid_val(cred->uid));
+       return -1;
 }
 
 /*