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 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 ----