changeset 9866:ddc5f1d8eb4e

6848431 zfs with rstchown=0 or file_chown_self privilege allows user to "take" ownership
author Mark Shellenbaum <Mark.Shellenbaum@Sun.COM>
date Mon, 15 Jun 2009 12:42:25 -0600
parents 60ebbe46c54a
children e368ccc44b16
files usr/src/uts/common/fs/zfs/zfs_acl.c usr/src/uts/common/os/policy.c usr/src/uts/common/sys/policy.h
diffstat 3 files changed, 25 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c	Mon Jun 15 12:04:28 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_acl.c	Mon Jun 15 12:42:25 2009 -0600
@@ -2366,8 +2366,7 @@
 		    secpolicy_vnode_access(cr, ZTOV(zp), owner, VREAD) == 0 ||
 		    secpolicy_vnode_access(cr, ZTOV(zp), owner, VWRITE) == 0 ||
 		    secpolicy_vnode_access(cr, ZTOV(zp), owner, VEXEC) == 0 ||
-		    secpolicy_vnode_chown(cr, B_TRUE) == 0 ||
-		    secpolicy_vnode_chown(cr, B_FALSE) == 0 ||
+		    secpolicy_vnode_chown(cr, owner) == 0 ||
 		    secpolicy_vnode_setdac(cr, owner) == 0 ||
 		    secpolicy_vnode_remove(cr) == 0);
 	}
@@ -2515,7 +2514,7 @@
 			    owner, checkmode);
 
 		if (error == 0 && (working_mode & ACE_WRITE_OWNER))
-			error = secpolicy_vnode_chown(cr, B_TRUE);
+			error = secpolicy_vnode_chown(cr, owner);
 		if (error == 0 && (working_mode & ACE_WRITE_ACL))
 			error = secpolicy_vnode_setdac(cr, owner);
 
@@ -2524,7 +2523,7 @@
 			error = secpolicy_vnode_remove(cr);
 
 		if (error == 0 && (working_mode & ACE_SYNCHRONIZE)) {
-			error = secpolicy_vnode_chown(cr, B_FALSE);
+			error = secpolicy_vnode_chown(cr, owner);
 		}
 		if (error == 0) {
 			/*
--- a/usr/src/uts/common/os/policy.c	Mon Jun 15 12:04:28 2009 -0700
+++ b/usr/src/uts/common/os/policy.c	Mon Jun 15 12:42:25 2009 -0600
@@ -929,16 +929,21 @@
  */
 
 int
-secpolicy_vnode_chown(const cred_t *cred, boolean_t check_self)
+secpolicy_vnode_chown(const cred_t *cred, uid_t owner)
 {
-	if (HAS_PRIVILEGE(cred, PRIV_FILE_CHOWN))
-		return (PRIV_POLICY(cred, PRIV_FILE_CHOWN, B_FALSE, EPERM,
-		    NULL));
-	else if (check_self)
-		return (PRIV_POLICY(cred, PRIV_FILE_CHOWN_SELF, B_FALSE, EPERM,
-		    NULL));
-	else
-		return (EPERM);
+	boolean_t is_owner = (owner == crgetuid(cred));
+	boolean_t allzone = B_FALSE;
+	int priv;
+
+	if (!is_owner) {
+		allzone = (owner == 0);
+		priv = PRIV_FILE_CHOWN;
+	} else {
+		priv = HAS_PRIVILEGE(cred, PRIV_FILE_CHOWN) ?
+		    PRIV_FILE_CHOWN : PRIV_FILE_CHOWN_SELF;
+	}
+
+	return (PRIV_POLICY(cred, priv, allzone, EPERM, NULL));
 }
 
 /*
@@ -951,7 +956,12 @@
 int
 secpolicy_vnode_create_gid(const cred_t *cred)
 {
-	return (secpolicy_vnode_chown(cred, B_TRUE));
+	if (HAS_PRIVILEGE(cred, PRIV_FILE_CHOWN))
+		return (PRIV_POLICY(cred, PRIV_FILE_CHOWN, B_FALSE, EPERM,
+		    NULL));
+	else
+		return (PRIV_POLICY(cred, PRIV_FILE_CHOWN_SELF, B_FALSE, EPERM,
+		    NULL));
 }
 
 /*
@@ -1211,8 +1221,6 @@
 
 	if (mask & (AT_UID|AT_GID)) {
 		boolean_t checkpriv = B_FALSE;
-		int priv;
-		boolean_t allzone = B_FALSE;
 
 		/*
 		 * Chowning files.
@@ -1232,23 +1240,18 @@
 		 */
 		if (cr->cr_uid != ovap->va_uid) {
 			checkpriv = B_TRUE;
-			allzone = (ovap->va_uid == 0);
-			priv = PRIV_FILE_CHOWN;
 		} else {
 			if (((mask & AT_UID) && vap->va_uid != ovap->va_uid) ||
 			    ((mask & AT_GID) && vap->va_gid != ovap->va_gid &&
 			    !groupmember(vap->va_gid, cr))) {
 				checkpriv = B_TRUE;
-				priv = HAS_PRIVILEGE(cr, PRIV_FILE_CHOWN) ?
-				    PRIV_FILE_CHOWN : PRIV_FILE_CHOWN_SELF;
 			}
 		}
 		/*
 		 * If necessary, check privilege to see if update can be done.
 		 */
 		if (checkpriv &&
-		    (error = PRIV_POLICY(cr, priv, allzone, EPERM, NULL))
-		    != 0) {
+		    (error = secpolicy_vnode_chown(cr, ovap->va_uid)) != 0) {
 			goto out;
 		}
 
--- a/usr/src/uts/common/sys/policy.h	Mon Jun 15 12:04:28 2009 -0700
+++ b/usr/src/uts/common/sys/policy.h	Mon Jun 15 12:42:25 2009 -0600
@@ -144,7 +144,7 @@
 int secpolicy_systeminfo(const cred_t *);
 int secpolicy_tasksys(const cred_t *);
 int secpolicy_vnode_access(const cred_t *, vnode_t *, uid_t, mode_t);
-int secpolicy_vnode_chown(const cred_t *, boolean_t);
+int secpolicy_vnode_chown(const cred_t *, uid_t);
 int secpolicy_vnode_create_gid(const cred_t *);
 int secpolicy_vnode_owner(const cred_t *, uid_t);
 int secpolicy_vnode_remove(const cred_t *);