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