Synopsis: race between sugid-exec and ptrace(2)
NetBSD versions: 1.4, 1.4.1, 1.4.2, 1.4.3
Thanks to: Jason Thorpe <
[email protected]>
Reported in NetBSD Security Advisory: NetBSD-SA2001-009
Index: sys/kern/exec_script.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/exec_script.c,v
retrieving revision 1.20.2.1
diff -p -p -c -r1.20.2.1 exec_script.c
*** sys/kern/exec_script.c 2000/02/01 23:11:20 1.20.2.1
--- sys/kern/exec_script.c 2001/07/16 09:06:10
*************** exec_script_makecmds(p, epp)
*** 146,153 ****
check_shell:
#ifdef SETUIDSCRIPTS
/*
! * MNT_NOSUID and STRC are already taken care of by check_exec,
! * so we don't need to worry about them now or later.
*/
script_sbits = epp->ep_vap->va_mode & (S_ISUID | S_ISGID);
if (script_sbits != 0) {
--- 146,154 ----
check_shell:
#ifdef SETUIDSCRIPTS
/*
! * MNT_NOSUID has already taken care of by check_exec,
! * so we don't need to worry about it now or later. We
! * will need to check P_TRACED later, however.
*/
script_sbits = epp->ep_vap->va_mode & (S_ISUID | S_ISGID);
if (script_sbits != 0) {
*************** check_shell:
*** 260,266 ****
#ifdef SETUIDSCRIPTS
/*
* set thing up so that set-id scripts will be
! * handled appropriately
*/
epp->ep_vap->va_mode |= script_sbits;
if (script_sbits & S_ISUID)
--- 261,269 ----
#ifdef SETUIDSCRIPTS
/*
* set thing up so that set-id scripts will be
! * handled appropriately. P_TRACED will be
! * checked later when the shell is actually
! * exec'd.
*/
epp->ep_vap->va_mode |= script_sbits;
if (script_sbits & S_ISUID)
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_exec.c,v
retrieving revision 1.100.2.3
diff -p -p -c -r1.100.2.3 kern_exec.c
*** sys/kern/kern_exec.c 2000/02/01 22:55:07 1.100.2.3
--- sys/kern/kern_exec.c 2001/07/16 09:06:11
*************** check_exec(p, epp)
*** 123,129 ****
error = EACCES;
goto bad1;
}
! if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED))
epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
/* try to open it */
--- 123,129 ----
error = EACCES;
goto bad1;
}
! if (vp->v_mount->mnt_flag & MNT_NOSUID)
epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
/* try to open it */
*************** sys_execve(p, v, retval)
*** 444,453 ****
/*
* deal with set[ug]id.
! * MNT_NOEXEC and P_TRACED have already been used to disable s[ug]id.
*/
! if (((attr.va_mode & S_ISUID) != 0 && p->p_ucred->cr_uid != attr.va_uid)
! || ((attr.va_mode & S_ISGID) != 0 && p->p_ucred->cr_gid != attr.va_gid)){
p->p_ucred = crcopy(cred);
#ifdef KTRACE
/*
--- 444,462 ----
/*
* deal with set[ug]id.
! * MNT_NOSUID has already been used to disable s[ug]id.
*/
! if ((p->p_flag & P_TRACED) == 0 &&
! (((attr.va_mode & S_ISUID) != 0 &&
! p->p_ucred->cr_uid != attr.va_uid) ||
! ((attr.va_mode & S_ISGID) != 0 &&
! p->p_ucred->cr_gid != attr.va_gid))) {
! /*
! * Mark the process as SUGID before we do
! * anything that might block.
! */
! p->p_flag |= P_SUGID;
!
p->p_ucred = crcopy(cred);
#ifdef KTRACE
/*
*************** sys_execve(p, v, retval)
*** 461,467 ****
p->p_ucred->cr_uid = attr.va_uid;
if (attr.va_mode & S_ISGID)
p->p_ucred->cr_gid = attr.va_gid;
- p->p_flag |= P_SUGID;
} else
p->p_flag &= ~P_SUGID;
p->p_cred->p_svuid = p->p_ucred->cr_uid;
--- 470,475 ----