[comp.bugs.4bsd.ucb-fixes] V1.77

bostic@OKEEFFE.BERKELEY.EDU (Keith Bostic) (01/29/89)

Subject: re-fix for chown security problem
Index: sys/ufs_syscalls.c 4.3BSD-tahoe

Description:
	There's a security problem associated with 4.3BSD and 4.3BSD-tahoe
	systems involving the chown(2) system call.  It may exist in
	4.3BSD derived systems; contact your vendor for more information.

	This is a second attempt at a correct fix; the fix posted on 16
	January 1989 is incorrect.  The attached fix is a diff from the 
	original version, not from the 16 January fix.
Fix:
	Apply the attached patch to sccsid version 7.3 of ufs_syscalls.c.

*** /tmp/d04748	Thu Jan 26 21:04:17 1989
--- ufs_syscalls.c	Wed Jan 25 09:44:50 1989
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ufs_syscalls.c	7.3 (Berkeley) 4/18/87
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ufs_syscalls.c	7.4 (Berkeley) 1/24/89
   */
  
  #include "param.h"
***************
*** 600,607 ****
  		int	uid;
  		int	gid;
  	} *uap = (struct a *)u.u_ap;
  
! 	if ((ip = owner(uap->fname, NOFOLLOW)) == NULL)
  		return;
  	u.u_error = chown1(ip, uap->uid, uap->gid);
  	iput(ip);
--- 600,612 ----
  		int	uid;
  		int	gid;
  	} *uap = (struct a *)u.u_ap;
+ 	register struct nameidata *ndp = &u.u_nd;
  
! 	ndp->ni_nameiop = LOOKUP | NOFOLLOW;
! 	ndp->ni_segflg = UIO_USERSPACE;
! 	ndp->ni_dirp = uap->fname;
! 	ip = namei(ndp);
! 	if (ip == NULL)
  		return;
  	u.u_error = chown1(ip, uap->uid, uap->gid);
  	iput(ip);
***************
*** 647,655 ****
  		uid = ip->i_uid;
  	if (gid == -1)
  		gid = ip->i_gid;
! 	if (uid != ip->i_uid && !suser())
! 		return (u.u_error);
! 	if (gid != ip->i_gid && !groupmember((gid_t)gid) && !suser())
  		return (u.u_error);
  #ifdef QUOTA
  	if (ip->i_uid == uid)		/* this just speeds things a little */
--- 652,664 ----
  		uid = ip->i_uid;
  	if (gid == -1)
  		gid = ip->i_gid;
! 	/*
! 	 * If we don't own the file, are trying to change the owner
! 	 * of the file, or are not a member of the target group,
! 	 * the caller must be superuser or the call fails.
! 	 */
! 	if ((u.u_uid != ip->i_uid || uid != ip->i_uid ||
! 	    !groupmember((gid_t)gid)) && !suser())
  		return (u.u_error);
  #ifdef QUOTA
  	if (ip->i_uid == uid)		/* this just speeds things a little */