summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2001-06-15 11:10:19 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2001-06-15 11:10:19 +0000
commit9680a34c3c5c28dbaeb36067ad52529b14e36654 (patch)
tree3f66011329aba3904b72ecef05b4ccdc2c02d821 /sys
parentc22afdde6f8ae460fef0316c2a3587f9d9edc687 (diff)
Avoid a dangerous race.
To avoid having a ptrace(2)d process from doing an exec of a suid binary we strip off the suid bits from the executable if the process is traced. Later we P_SUGID{,EXEC} in the process flags that stops further ptrace attempts. The problem is that between the stripping of suid bits and setting P_SUGID{,EXEC} there is a pretty large window where the process can sleep and other processes can attach to it with ptrace. This is a quick fix for that. We set P_SUGID{,EXEC} early and take care to remove them (we don't want the process to become tainted unnecessarily) if exec fails. XXX - exec needs a lot more work, but people are asking for a solution now.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_exec.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 0b44d27d700..d62cd072bac 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exec.c,v 1.48 2001/04/01 21:30:33 art Exp $ */
+/* $OpenBSD: kern_exec.c,v 1.49 2001/06/15 11:10:18 art Exp $ */
/* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
/*-
@@ -133,6 +133,15 @@ check_exec(p, epp)
(p->p_flag & P_TRACED) || p->p_fd->fd_refcnt > 1)
epp->ep_vap->va_mode &= ~(VSUID | VSGID);
+ /*
+ * Set the P_SUID* flags early so that we won't be fiddled with when
+ * we sleep later in this code.
+ * XXX - this could give us a few false positives and the caller must
+ * make sure to save and restore the flags if exec fails.
+ */
+ if (epp->ep_vap->va_mode & (VSUID|VSGID))
+ p->p_flag |= P_SUGID|P_SUGIDEXEC;
+
/* check access. for root we have to see if any exec bit on */
if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0)
goto bad1;
@@ -244,6 +253,7 @@ sys_execve(p, v, retval)
char **tmpfap;
int szsigcode;
extern struct emul emul_native;
+ int saved_sugid;
/*
* figure out the maximum size of an exec header, if necessary.
@@ -274,6 +284,7 @@ sys_execve(p, v, retval)
pack.ep_emul = &emul_native;
pack.ep_flags = 0;
+ saved_sugid = p->p_flag & (P_SUGID|P_SUGIDEXEC);
/* see if we can run it. */
if ((error = check_exec(p, &pack)) != 0) {
goto freehdr;
@@ -646,6 +657,7 @@ bad:
freehdr:
free(pack.ep_hdr, M_EXEC);
+ p->p_flag = (p->p_flag & ~(P_SUGID|P_SUGIDEXEC)) | saved_sugid;
return (error);
exec_abort: