Module Name:    src
Committed By:   elad
Date:           Mon Apr 20 18:06:27 UTC 2009

Modified Files:
        src/sys/fs/ptyfs: ptyfs_vnops.c
        src/sys/fs/tmpfs: tmpfs_subr.c
        src/sys/fs/udf: udf_vnops.c
        src/sys/kern: vfs_subr.c
        src/sys/sys: vnode.h
        src/sys/ufs/ext2fs: ext2fs_vnops.c
        src/sys/ufs/ufs: ufs_vnops.c

Log Message:
Refactor some duplicated file-system code.

Proposed and received no objections on tech-kern@:

        http://mail-index.netbsd.org/tech-kern/2009/04/18/msg004843.html


To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 src/sys/fs/ptyfs/ptyfs_vnops.c
cvs rdiff -u -r1.50 -r1.51 src/sys/fs/tmpfs/tmpfs_subr.c
cvs rdiff -u -r1.38 -r1.39 src/sys/fs/udf/udf_vnops.c
cvs rdiff -u -r1.371 -r1.372 src/sys/kern/vfs_subr.c
cvs rdiff -u -r1.203 -r1.204 src/sys/sys/vnode.h
cvs rdiff -u -r1.83 -r1.84 src/sys/ufs/ext2fs/ext2fs_vnops.c
cvs rdiff -u -r1.173 -r1.174 src/sys/ufs/ufs/ufs_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/ptyfs/ptyfs_vnops.c
diff -u src/sys/fs/ptyfs/ptyfs_vnops.c:1.27 src/sys/fs/ptyfs/ptyfs_vnops.c:1.28
--- src/sys/fs/ptyfs/ptyfs_vnops.c:1.27	Wed Jan  2 11:48:43 2008
+++ src/sys/fs/ptyfs/ptyfs_vnops.c	Mon Apr 20 18:06:27 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ptyfs_vnops.c,v 1.27 2008/01/02 11:48:43 ad Exp $	*/
+/*	$NetBSD: ptyfs_vnops.c,v 1.28 2009/04/20 18:06:27 elad Exp $	*/
 
 /*
  * Copyright (c) 1993, 1995
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops.c,v 1.27 2008/01/02 11:48:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops.c,v 1.28 2009/04/20 18:06:27 elad Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -464,10 +464,11 @@
 	struct ptyfsnode *ptyfs = VTOPTYFS(vp);
 	int error;
 
-	if (kauth_cred_geteuid(cred) != ptyfs->ptyfs_uid &&
-	    (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
-	    NULL)) != 0)
-		return error;
+	error = common_chmod_allowed(cred, vp, ptyfs->ptyfs_uid,
+	    ptyfs->ptyfs_gid, mode);
+	if (error)
+		return (error);
+
 	ptyfs->ptyfs_mode &= ~ALLPERMS;
 	ptyfs->ptyfs_mode |= (mode & ALLPERMS);
 	return 0;
@@ -482,25 +483,17 @@
     struct lwp *l)
 {
 	struct ptyfsnode *ptyfs = VTOPTYFS(vp);
-	int		error, ismember = 0;
+	int error;
 
 	if (uid == (uid_t)VNOVAL)
 		uid = ptyfs->ptyfs_uid;
 	if (gid == (gid_t)VNOVAL)
 		gid = ptyfs->ptyfs_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's credentials must imply super-user privilege
-	 * or the call fails.
-	 */
-	if ((kauth_cred_geteuid(cred) != ptyfs->ptyfs_uid || uid != ptyfs->ptyfs_uid ||
-	    (gid != ptyfs->ptyfs_gid &&
-	    !(kauth_cred_getegid(cred) == gid ||
-	    (kauth_cred_ismember_gid(cred, gid, &ismember) == 0 && ismember)))) &&
-	    ((error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
-	    NULL)) != 0))
-		return error;
+
+	error = common_chown_allowed(cred, ptyfs->ptyfs_uid, ptyfs->ptyfs_gid,
+	    uid, gid);
+	if (error)
+		return (error);
 
 	ptyfs->ptyfs_gid = gid;
 	ptyfs->ptyfs_uid = uid;

Index: src/sys/fs/tmpfs/tmpfs_subr.c
diff -u src/sys/fs/tmpfs/tmpfs_subr.c:1.50 src/sys/fs/tmpfs/tmpfs_subr.c:1.51
--- src/sys/fs/tmpfs/tmpfs_subr.c:1.50	Sat Apr 11 11:59:04 2009
+++ src/sys/fs/tmpfs/tmpfs_subr.c	Mon Apr 20 18:06:27 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_subr.c,v 1.50 2009/04/11 11:59:04 markd Exp $	*/
+/*	$NetBSD: tmpfs_subr.c,v 1.51 2009/04/20 18:06:27 elad Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.50 2009/04/11 11:59:04 markd Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.51 2009/04/20 18:06:27 elad Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -1018,7 +1018,7 @@
 int
 tmpfs_chmod(struct vnode *vp, mode_t mode, kauth_cred_t cred, struct lwp *l)
 {
-	int error, ismember = 0;
+	int error;
 	struct tmpfs_node *node;
 
 	KASSERT(VOP_ISLOCKED(vp));
@@ -1033,21 +1033,10 @@
 	if (node->tn_flags & (IMMUTABLE | APPEND))
 		return EPERM;
 
-	/* XXX: The following comes from UFS code, and can be found in
-	 * several other file systems.  Shouldn't this be centralized
-	 * somewhere? */
-	if (kauth_cred_geteuid(cred) != node->tn_uid &&
-	    (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
-	    NULL)))
-		return error;
-	if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0) {
-		if (vp->v_type != VDIR && (mode & S_ISTXT))
-			return EFTYPE;
-
-		if ((kauth_cred_ismember_gid(cred, node->tn_gid,
-		    &ismember) != 0 || !ismember) && (mode & S_ISGID))
-			return EPERM;
-	}
+	error = common_chmod_allowed(cred, vp, node->tn_uid, node->tn_gid,
+	    mode);
+	if (error)
+		return (error);
 
 	node->tn_mode = (mode & ALLPERMS);
 
@@ -1072,7 +1061,7 @@
 tmpfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
     struct lwp *l)
 {
-	int error, ismember = 0;
+	int error;
 	struct tmpfs_node *node;
 
 	KASSERT(VOP_ISLOCKED(vp));
@@ -1095,15 +1084,10 @@
 	if (node->tn_flags & (IMMUTABLE | APPEND))
 		return EPERM;
 
-	/* XXX: The following comes from UFS code, and can be found in
-	 * several other file systems.  Shouldn't this be centralized
-	 * somewhere? */
-	if ((kauth_cred_geteuid(cred) != node->tn_uid || uid != node->tn_uid ||
-	    (gid != node->tn_gid && !(kauth_cred_getegid(cred) == gid ||
-	    (kauth_cred_ismember_gid(cred, gid, &ismember) == 0 && ismember)))) &&
-	    ((error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
-	    NULL)) != 0))
-		return error;
+	error = common_chown_allowed(cred, node->tn_uid, node->tn_gid, uid,
+	    gid);
+	if (error)
+		return (error);
 
 	node->tn_uid = uid;
 	node->tn_gid = gid;

Index: src/sys/fs/udf/udf_vnops.c
diff -u src/sys/fs/udf/udf_vnops.c:1.38 src/sys/fs/udf/udf_vnops.c:1.39
--- src/sys/fs/udf/udf_vnops.c:1.38	Fri Mar 20 23:06:52 2009
+++ src/sys/fs/udf/udf_vnops.c	Mon Apr 20 18:06:26 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_vnops.c,v 1.38 2009/03/20 23:06:52 reinoud Exp $ */
+/* $NetBSD: udf_vnops.c,v 1.39 2009/04/20 18:06:26 elad Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.38 2009/03/20 23:06:52 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.39 2009/04/20 18:06:26 elad Exp $");
 #endif /* not lint */
 
 
@@ -935,9 +935,8 @@
 	  kauth_cred_t cred)
 {
 	struct udf_node  *udf_node = VTOI(vp);
-	uid_t euid, uid;
-	gid_t egid, gid;
-	int issuperuser, ismember;
+	uid_t uid;
+	gid_t gid;
 	int error;
 
 #ifdef notyet
@@ -965,26 +964,10 @@
 	if ((gid_t) ((uint32_t) gid) != gid)
 		return EINVAL;
 
-	/*
-	 * 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's
-	 * credentials must imply super-user privilege or the call fails.
-	 */
-
 	/* check permissions */
-	euid  = kauth_cred_geteuid(cred);
-	egid  = kauth_cred_getegid(cred);
-	if ((error = kauth_cred_ismember_gid(cred, new_gid, &ismember)))
-		return error;
-	error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
-	issuperuser = (error == 0);
-
-	if (!issuperuser) {
-		if ((new_uid != uid) || (euid != uid))
-			return EPERM;
-		if ((new_gid != gid) && !(egid == new_gid || ismember)) 
-			return EPERM;
-	}
+	error = common_chown_allowed(cred, uid, gid, new_uid, new_gid);
+	if (error)
+		return (error);
 
 	/* change the ownership */
 	udf_setownership(udf_node, new_uid, new_gid);
@@ -1000,9 +983,8 @@
 udf_chmod(struct vnode *vp, mode_t mode, kauth_cred_t cred)
 {
 	struct udf_node  *udf_node = VTOI(vp);
-	uid_t euid, uid;
-	gid_t egid, gid;
-	int issuperuser, ismember;
+	uid_t uid;
+	gid_t gid;
 	int error;
 
 #ifdef notyet
@@ -1019,22 +1001,9 @@
 	udf_getownership(udf_node, &uid, &gid);
 
 	/* check permissions */
-	euid  = kauth_cred_geteuid(cred);
-	egid  = kauth_cred_getegid(cred);
-	if ((error = kauth_cred_ismember_gid(cred, gid, &ismember)))
-		return error;
-	error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
-	issuperuser = (error == 0);
-
-	if ((euid != uid) && !issuperuser)
-		return EPERM;
-	if (euid != 0) {
-		if (vp->v_type != VDIR && (mode & S_ISTXT))
-			return EFTYPE;
-
-		if ((!ismember) && (mode & S_ISGID))
-			return EPERM;
-	}
+	error = common_chmod_allowed(cred, vp, uid, gid, mode);
+	if (error)
+		return (error);
 
 	/* change mode */
 	udf_setaccessmode(udf_node, mode);

Index: src/sys/kern/vfs_subr.c
diff -u src/sys/kern/vfs_subr.c:1.371 src/sys/kern/vfs_subr.c:1.372
--- src/sys/kern/vfs_subr.c:1.371	Fri Apr 17 20:22:52 2009
+++ src/sys/kern/vfs_subr.c	Mon Apr 20 18:06:26 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_subr.c,v 1.371 2009/04/17 20:22:52 dyoung Exp $	*/
+/*	$NetBSD: vfs_subr.c,v 1.372 2009/04/20 18:06:26 elad Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc.
@@ -81,7 +81,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.371 2009/04/17 20:22:52 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.372 2009/04/20 18:06:26 elad Exp $");
 
 #include "opt_ddb.h"
 #include "opt_compat_netbsd.h"
@@ -3206,3 +3206,147 @@
 	}
 }
 #endif /* DDB */
+
+/*
+ * Common routine to check if chmod() is allowed.
+ *
+ * Policy:
+ *   - You must be root, or
+ *   - You must own the file, and
+ *     - You must not set the "sticky" bit (meaningless, see chmod(2))
+ *     - You must be a member of the group if you're trying to set the
+ *       SGIDf bit
+ *
+ * cred - credentials of the invoker
+ * vp - vnode of the file-system object
+ * cur_uid, cur_gid - current uid/gid of the file-system object
+ * new_mode - new mode for the file-system object
+ *
+ * Returns 0 if the change is allowed, or an error value otherwise.
+ */
+int
+common_chmod_allowed(kauth_cred_t cred, struct vnode *vp, uid_t cur_uid,
+    gid_t cur_gid, mode_t new_mode)
+{
+	int error;
+
+	/* Superuser can always change mode. */
+	error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
+	    NULL);
+	if (!error) {
+		goto out;
+	}
+
+	/* Otherwise, user must own the file. */
+	if (kauth_cred_geteuid(cred) != cur_uid) {
+		goto out;
+	}
+
+	/*
+	 * Non-root users can't set the sticky bit on files.
+	 */
+	if ((vp->v_type != VDIR) && (new_mode & S_ISTXT)) {
+		error = EFTYPE;
+		goto out;
+	}
+
+	/*
+	 * If the invoker is trying to set the SGID bit on the file,
+	 * check group membership.
+	 */
+	if (new_mode & S_ISGID) {
+		int ismember;
+
+		error = kauth_cred_ismember_gid(cred, cur_gid,
+		    &ismember);
+		if (error)
+			goto out;
+
+		if (!ismember) {
+			error = EPERM;
+			goto out;
+		}
+	}
+
+	error = 0;
+
+ out:
+	return (error);
+}
+
+/*
+ * Common routine to check if chown() is allowed.
+ *
+ * Policy:
+ *   - You must be root, or
+ *   - You must own the file, and
+ *     - You must not try to change ownership, and
+ *     - You must be member of the new group
+ *
+ * cred - credentials of the invoker
+ * cur_uid, cur_gid - current uid/gid of the file-system object
+ * new_uid, new_gid - target uid/gid of the file-system object
+ *
+ * Returns 0 if the change is allowed, or an error value otherwise.
+ */
+int	
+common_chown_allowed(kauth_cred_t cred, uid_t cur_uid, gid_t cur_gid,
+    uid_t new_uid, gid_t new_gid)
+{
+	int error, ismember;
+
+	/*
+	 * You can only change ownership of a file if:
+	 * You are the superuser, or...
+	 */
+	error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
+	    NULL);
+	if (!error) {
+		goto out;
+	}
+
+	/*
+	 * You own the file and...
+	 */
+	if (kauth_cred_geteuid(cred) == cur_uid) {
+		/*
+		 * You don't try to change ownership, and...
+		 */
+		 if (new_uid != cur_uid) {
+			goto out;
+		}
+
+		/*
+		 * You don't try to change group (no-op), or...
+		 */
+		if (new_gid == cur_gid) {
+			error = 0;
+			goto out;
+		}
+
+		/*
+		 * Your effective gid is the new gid, or...
+		 */
+		if (kauth_cred_getegid(cred) == new_gid) {
+			error = 0;
+			goto out;
+		}
+
+		/*
+		 * The new gid is one you're a member of.
+		 */
+		ismember = 0;
+		error = kauth_cred_ismember_gid(cred, new_gid,
+		    &ismember);
+		if (error || !ismember) {
+			error = EPERM;
+			goto out;
+		}
+
+		error = 0;
+	}
+
+ out:
+	return (error);
+}
+

Index: src/sys/sys/vnode.h
diff -u src/sys/sys/vnode.h:1.203 src/sys/sys/vnode.h:1.204
--- src/sys/sys/vnode.h:1.203	Thu Mar 19 09:07:54 2009
+++ src/sys/sys/vnode.h	Mon Apr 20 18:06:26 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: vnode.h,v 1.203 2009/03/19 09:07:54 pooka Exp $	*/
+/*	$NetBSD: vnode.h,v 1.204 2009/04/20 18:06:26 elad Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -663,6 +663,10 @@
 void	vfs_vnode_print(struct vnode *, int, void (*)(const char *, ...));
 void	vfs_mount_print(struct mount *, int, void (*)(const char *, ...));
 #endif /* DDB */
+
+int	common_chmod_allowed(kauth_cred_t, struct vnode *, uid_t, gid_t,
+	    mode_t);
+int	common_chown_allowed(kauth_cred_t, uid_t, gid_t, uid_t, gid_t);
 #endif /* _KERNEL */
 
 #endif /* !_SYS_VNODE_H_ */

Index: src/sys/ufs/ext2fs/ext2fs_vnops.c
diff -u src/sys/ufs/ext2fs/ext2fs_vnops.c:1.83 src/sys/ufs/ext2fs/ext2fs_vnops.c:1.84
--- src/sys/ufs/ext2fs/ext2fs_vnops.c:1.83	Sun Nov 23 10:09:25 2008
+++ src/sys/ufs/ext2fs/ext2fs_vnops.c	Mon Apr 20 18:06:27 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_vnops.c,v 1.83 2008/11/23 10:09:25 mrg Exp $	*/
+/*	$NetBSD: ext2fs_vnops.c,v 1.84 2009/04/20 18:06:27 elad Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.83 2008/11/23 10:09:25 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.84 2009/04/20 18:06:27 elad Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -442,19 +442,12 @@
 ext2fs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct lwp *l)
 {
 	struct inode *ip = VTOI(vp);
-	int error, ismember = 0;
+	int error;
 
-	if (kauth_cred_geteuid(cred) != ip->i_uid &&
-	    (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
-	    NULL)))
+	error = common_chmod_allowed(cred, vp, ip->i_uid, ip->i_gid, mode);
+	if (error)
 		return (error);
-	if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL)) {
-		if (vp->v_type != VDIR && (mode & S_ISTXT))
-			return (EFTYPE);
-		if ((kauth_cred_ismember_gid(cred, ip->i_gid, &ismember) != 0 ||
-		    !ismember) && (mode & ISGID))
-			return (EPERM);
-	}
+
 	ip->i_e2fs_mode &= ~ALLPERMS;
 	ip->i_e2fs_mode |= (mode & ALLPERMS);
 	ip->i_flag |= IN_CHANGE;
@@ -472,23 +465,17 @@
 	struct inode *ip = VTOI(vp);
 	uid_t ouid;
 	gid_t ogid;
-	int error = 0, ismember = 0;
+	int error;
 
 	if (uid == (uid_t)VNOVAL)
 		uid = ip->i_uid;
 	if (gid == (gid_t)VNOVAL)
 		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 ((kauth_cred_geteuid(cred) != ip->i_uid || uid != ip->i_uid ||
- 	    (gid != ip->i_gid &&
-	    !(kauth_cred_getegid(cred) == gid ||
-	    (kauth_cred_ismember_gid(cred, gid, &ismember) == 0 && ismember)))) &&
-	    (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL)))
+
+	error = common_chown_allowed(cred, ip->i_uid, ip->i_gid, uid, gid);
+	if (error)
 		return (error);
+
 	ogid = ip->i_gid;
 	ouid = ip->i_uid;
 

Index: src/sys/ufs/ufs/ufs_vnops.c
diff -u src/sys/ufs/ufs/ufs_vnops.c:1.173 src/sys/ufs/ufs/ufs_vnops.c:1.174
--- src/sys/ufs/ufs/ufs_vnops.c:1.173	Sun Feb 22 20:28:07 2009
+++ src/sys/ufs/ufs/ufs_vnops.c	Mon Apr 20 18:06:27 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_vnops.c,v 1.173 2009/02/22 20:28:07 ad Exp $	*/
+/*	$NetBSD: ufs_vnops.c,v 1.174 2009/04/20 18:06:27 elad Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.173 2009/02/22 20:28:07 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.174 2009/04/20 18:06:27 elad Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -640,21 +640,16 @@
 ufs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct lwp *l)
 {
 	struct inode	*ip;
-	int		error, ismember = 0;
+	int		error;
 
 	UFS_WAPBL_JLOCK_ASSERT(vp->v_mount);
 
 	ip = VTOI(vp);
-	if (kauth_cred_geteuid(cred) != ip->i_uid &&
-	    (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL)))
+
+	error = common_chmod_allowed(cred, vp, ip->i_uid, ip->i_gid, mode);
+	if (error)
 		return (error);
-	if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL)) {
-		if (vp->v_type != VDIR && (mode & S_ISTXT))
-			return (EFTYPE);
-		if ((kauth_cred_ismember_gid(cred, ip->i_gid, &ismember) != 0 ||
-		    !ismember) && (mode & ISGID))
-			return (EPERM);
-	}
+
 	ip->i_mode &= ~ALLPERMS;
 	ip->i_mode |= (mode & ALLPERMS);
 	ip->i_flag |= IN_CHANGE;
@@ -672,7 +667,7 @@
     	struct lwp *l)
 {
 	struct inode	*ip;
-	int		error, ismember = 0;
+	int		error = 0;
 #ifdef QUOTA
 	uid_t		ouid;
 	gid_t		ogid;
@@ -685,19 +680,9 @@
 		uid = ip->i_uid;
 	if (gid == (gid_t)VNOVAL)
 		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's credentials must imply super-user privilege
-	 * or the call fails.
-	 */
-	if ((kauth_cred_geteuid(cred) != ip->i_uid || uid != ip->i_uid ||
-	    (gid != ip->i_gid &&
-	    !(kauth_cred_getegid(cred) == gid ||
-	    (kauth_cred_ismember_gid(cred, gid, &ismember) == 0 &&
-	    ismember)))) &&
-	    ((error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
-	    NULL)) != 0))
+
+	error = common_chown_allowed(cred, ip->i_uid, ip->i_gid, uid, gid);
+	if (error)
 		return (error);
 
 #ifdef QUOTA

Reply via email to