<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">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 &lt;thorpej@netbsd.org&gt;
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-&gt;ep_vap-&gt;va_mode &amp; (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-&gt;ep_vap-&gt;va_mode &amp; (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-&gt;ep_vap-&gt;va_mode |= script_sbits;
  		if (script_sbits &amp; 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-&gt;ep_vap-&gt;va_mode |= script_sbits;
  		if (script_sbits &amp; 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-&gt;v_mount-&gt;mnt_flag &amp; MNT_NOSUID) || (p-&gt;p_flag &amp; P_TRACED))
  		epp-&gt;ep_vap-&gt;va_mode &amp;= ~(S_ISUID | S_ISGID);
  
  	/* try to open it */
--- 123,129 ----
  		error = EACCES;
  		goto bad1;
  	}
! 	if (vp-&gt;v_mount-&gt;mnt_flag &amp; MNT_NOSUID)
  		epp-&gt;ep_vap-&gt;va_mode &amp;= ~(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 &amp; S_ISUID) != 0 &amp;&amp; p-&gt;p_ucred-&gt;cr_uid != attr.va_uid)
! 	 || ((attr.va_mode &amp; S_ISGID) != 0 &amp;&amp; p-&gt;p_ucred-&gt;cr_gid != attr.va_gid)){
  		p-&gt;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-&gt;p_flag &amp; P_TRACED) == 0 &amp;&amp;
! 	    (((attr.va_mode &amp; S_ISUID) != 0 &amp;&amp;
! 	      p-&gt;p_ucred-&gt;cr_uid != attr.va_uid) ||
! 	     ((attr.va_mode &amp; S_ISGID) != 0 &amp;&amp;
! 	      p-&gt;p_ucred-&gt;cr_gid != attr.va_gid))) {
! 		/*
! 		 * Mark the process as SUGID before we do
! 		 * anything that might block.
! 		 */
! 		p-&gt;p_flag |= P_SUGID;
! 
  		p-&gt;p_ucred = crcopy(cred);
  #ifdef KTRACE
  		/*
*************** sys_execve(p, v, retval)
*** 461,467 ****
  			p-&gt;p_ucred-&gt;cr_uid = attr.va_uid;
  		if (attr.va_mode &amp; S_ISGID)
  			p-&gt;p_ucred-&gt;cr_gid = attr.va_gid;
- 		p-&gt;p_flag |= P_SUGID;
  	} else
  		p-&gt;p_flag &amp;= ~P_SUGID;
  	p-&gt;p_cred-&gt;p_svuid = p-&gt;p_ucred-&gt;cr_uid;
--- 470,475 ----
</pre></body></html>