diff mbox series

[10/11] exec: In bprm_fill_uid set secureexec at same time as per_clear

Message ID 87sgfkvz2m.fsf_-_@x220.int.ebiederm.org (mailing list archive)
State New, archived
Headers show
Series [01/11] exec: Reduce bprm->per_clear to a single bit | expand

Commit Message

Eric W. Biederman May 28, 2020, 3:50 p.m. UTC
We currently have two different policies for setting per_clear and for
setting secureexec.  For per_clear the policy is if the setxid bits on
a file are honored.  For secureexec the policy is if the resulting
credentials will have multiple uids or gids.

Looking closely the policy for setting AT_SECURE and asking userspace
not to trust our caller in all cases where we have multiple uids or
gids does not make sense.   In some of those cases it is the caller
of exec that provides multiple uids and gids.

The point of setting AT_SECURE is so that the called application or
it's libraries can take defensive measures to guard against a lesser
privileged program which calls it via exec.  If all of your privilege
comes from your caller there is no point in taking defensive measures,
against them.

Further the only way that libc or other userspace can know that the
privilege came from the caller of exec and not from the exec being
suid or sgid is by the kernel telling it.  As userspace does not
have enough information to distinguish between these two cases.

So set secureexec when the exec itself results in multiple uids
or gids, not when we happen to have mulitple ids because the
binary was called that way.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
 fs/exec.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/fs/exec.c b/fs/exec.c
index 347dade4bc54..fc4edc7517a6 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1637,19 +1637,19 @@  static void bprm_fill_uid(struct linux_binprm *bprm)
 	if ((mode & S_ISUID) &&
 	    (!need_cap || ns_capable(new->user_ns, CAP_SETUID))) {
 		bprm->per_clear = 1;
+		bprm->secureexec = 1;
 		new->suid = new->fsuid = new->euid = uid;
 	}
 
 	if (((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) &&
 	    (!need_cap || ns_capable(new->user_ns, CAP_SETGID))) {
 		bprm->per_clear = 1;
+		bprm->secureexec = 1;
 		new->sgid = new->fsgid = 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))
-		bprm->secureexec = 1;
+	;
 }
 
 /*