diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2001-06-15 11:10:19 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2001-06-15 11:10:19 +0000 |
commit | 9680a34c3c5c28dbaeb36067ad52529b14e36654 (patch) | |
tree | 3f66011329aba3904b72ecef05b4ccdc2c02d821 /sys | |
parent | c22afdde6f8ae460fef0316c2a3587f9d9edc687 (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.c | 14 |
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: |