lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <87ftbkxdqc.fsf_-_@x220.int.ebiederm.org>
Date:   Thu, 28 May 2020 10:48:11 -0500
From:   ebiederm@...ssion.com (Eric W. Biederman)
To:     <linux-kernel@...r.kernel.org>
Cc:     Linus Torvalds <torvalds@...ux-foundation.org>,
        Oleg Nesterov <oleg@...hat.com>, Jann Horn <jannh@...gle.com>,
        Kees Cook <keescook@...omium.org>,
        Greg Ungerer <gerg@...ux-m68k.org>,
        Rob Landley <rob@...dley.net>,
        Bernd Edlinger <bernd.edlinger@...mail.de>,
        <linux-fsdevel@...r.kernel.org>, Al Viro <viro@...IV.linux.org.uk>,
        Alexey Dobriyan <adobriyan@...il.com>,
        Andrew Morton <akpm@...ux-foundation.org>,
        Casey Schaufler <casey@...aufler-ca.com>,
        linux-security-module@...r.kernel.org,
        James Morris <jmorris@...ei.org>,
        "Serge E. Hallyn" <serge@...lyn.com>,
        Andy Lutomirski <luto@...capital.net>
Subject: [PATCH 06/11] exec: Don't set secureexec when the uid or gid changes are abandoned


When the is_secureexec test was removed from cap_bprm_set_creds the
test was modified so that it based the status of secureexec on a
version of the euid and egid before ptrace and shared fs tests
possibly reverted them.

The effect of which is that secureexec continued to be set when the
euid and egid change were abandoned because the executable was being
ptraced to secureexec being set in that same situation.

As far as I can tell it is just an oversight and very poor quality of
implementation to set AT_SECURE when it is not ncessary.  So improve
the quality of the implementation by only setting secureexec when there
will be multiple uids or gids in the final cred structure.

Fixes: ee67ae7ef6ff ("commoncap: Move cap_elevated calculation into bprm_set_creds")
Signed-off-by: "Eric W. Biederman" <ebiederm@...ssion.com>
---
 fs/exec.c | 48 +++++++++++++++++++++---------------------------
 1 file changed, 21 insertions(+), 27 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index bac8db14f30d..123402f218fe 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1622,44 +1622,38 @@ static void bprm_fill_uid(struct linux_binprm *bprm)
 	    !kgid_has_mapping(new->user_ns, gid))
 		goto after_setid;
 
+	/*
+	 * Is the root directory and working directory shared or is
+	 * the process traced and the tracing process does not have
+	 * CAP_SYS_PTRACE?
+	 *
+	 * In either case it is not safe to change the euid or egid
+	 * unless the current process has the appropriate cap and so
+	 * chaning the euid or egid was already possible.
+	 */
+	need_cap = bprm->unsafe & LSM_UNSAFE_SHARE ||
+		!ptracer_capable(current, new->user_ns);
+
 	if (mode & S_ISUID) {
 		bprm->per_clear = 1;
-		new->euid = uid;
+		if (!need_cap ||
+		    (ns_capable(new->user_ns, CAP_SETUID) &&
+		     !(bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)))
+			new->euid = uid;
 	}
-
 	if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
 		bprm->per_clear = 1;
-		new->egid = gid;
+		if (!need_cap ||
+		    (ns_capable(new->user_ns, CAP_SETGID) &&
+		     !(bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)))
+			new->egid = gid;
 	}
 
 after_setid:
 	/* Will the new creds have multiple uids or gids? */
-	if (!uid_eq(new->euid, new->uid) || !gid_eq(new->egid, new->gid)) {
+	if (!uid_eq(new->euid, new->uid) || !gid_eq(new->egid, new->gid))
 		bprm->secureexec = 1;
 
-		/*
-		 * Is the root directory and working directory shared or is
-		 * the process traced and the tracing process does not have
-		 * CAP_SYS_PTRACE?
-		 *
-		 * In either case it is not safe to change the euid or egid
-		 * unless the current process has the appropriate cap and so
-		 * chaning the euid or egid was already possible.
-		 */
-		need_cap = bprm->unsafe & LSM_UNSAFE_SHARE ||
-			!ptracer_capable(current, new->user_ns);
-		if (need_cap && !uid_eq(new->euid, new->uid) &&
-		    (!ns_capable(new->user_ns, CAP_SETUID) ||
-		     (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))) {
-			new->euid = new->uid;
-		}
-		if (need_cap && !gid_eq(new->egid, new->gid) &&
-		    (!ns_capable(new->user_ns, CAP_SETGID) ||
-		     (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))) {
-			new->egid = new->gid;
-		}
-	}
-
 	new->suid = new->fsuid = new->euid;
 	new->sgid = new->fsgid = new->egid;
 }
-- 
2.25.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ