Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Jul 2008 12:19:58 GMT
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 144877 for review
Message-ID:  <200807081219.m68CJwCT035698@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=144877

Change 144877 by trasz@trasz_traszkan on 2008/07/08 12:19:26

	First part of granular permission checking.  VOP_GRANULAR is supposed
	to be temporary.  Also, some cleanup.
	
	Merging this by hand is getting ugly.  ;-/

Affected files ...

.. //depot/projects/soc2008/trasz_nfs4acl/lib/libc/posix1e/acl_flags_nfs4.c#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/subr_acl_nfs4.c#6 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/subr_acl_posix1e.c#3 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_default.c#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_subr.c#3 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_vnops.c#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vnode_if.src#4 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/sys/acl.h#11 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/sys/vnode.h#3 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ffs/ffs_vnops.c#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_acl.c#6 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_extattr.c#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_vnops.c#6 edit

Differences ...

==== //depot/projects/soc2008/trasz_nfs4acl/lib/libc/posix1e/acl_flags_nfs4.c#2 (text+ko) ====

@@ -42,8 +42,8 @@
      { ACL_ENTRY_DIRECTORY_INHERIT, "dir_inherit", 'd'},
      { ACL_ENTRY_ONLY_INHERIT, "inherit_only", 'i'},
      { ACL_ENTRY_LIMIT_INHERIT, "no_propagate", 'n'},
-     { ACL_FLAG_SUCCESSFUL_ACCESS, "successfull_access", 'S'},
-     { ACL_FLAG_FAILED_ACCESS, "failed_access", 'F'},
+     { ACL_ENTRY_SUCCESSFUL_ACCESS, "successfull_access", 'S'},
+     { ACL_ENTRY_FAILED_ACCESS, "failed_access", 'F'},
      /*
       * There is no ACE_IDENTIFIER_GROUP here - SunOS does not show it
       * in the "flags" field.  There is no ACE_OWNER, ACE_GROUP or

==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/subr_acl_nfs4.c#6 (text+ko) ====

@@ -52,6 +52,48 @@
 
 #ifdef _KERNEL
 static int
+_access_mask_from_mode(mode_t mode)
+{
+	int access_mask = 0;
+
+	/* XXX: VSTAT? */
+
+	if (mode & VREAD)
+		access_mask |= ACL_READ_DATA;
+
+	if (mode & VWRITE)
+		access_mask |= ACL_WRITE_DATA;
+
+	if (mode & VAPPEND) {
+		/*
+		 * Translate from open(2) semantics to NFSv4 one.
+		 * In order to open file for writing, one needs
+		 * to specify both O_WRONLY and O_APPEND.  With NFSv4,
+		 * permission to write is not required to append,
+		 * permission to append is sufficient.
+		 */
+		access_mask |= ACL_APPEND_DATA;
+		access_mask &= ~ACL_WRITE_DATA;
+	}
+
+	if (mode & VEXEC)
+		access_mask |= ACL_EXECUTE;
+
+	if (mode & VADMIN)
+		access_mask |= (ACL_WRITE_NAMED_ATTRS |
+		    ACL_WRITE_ATTRIBUTES | ACL_WRITE_ACL |
+		    ACL_WRITE_OWNER);
+
+	return (access_mask);
+}
+
+/*
+ * Remove bits that are set in entry->ae_perm from *needed_bits.
+ * Return -1 if entry type is "deny" and bits match, 0 otherwise.
+ *
+ * XXX: Find a better name.
+ */
+static int
 _match_bits(const struct acl_entry *entry, int *needed_bits)
 {
 	if (entry->ae_extended == ACL_EXTENDED_DENY) {
@@ -64,32 +106,18 @@
 	return (0);
 }
 
-int
-vaccess_acl_nfs4(enum vtype type, uid_t file_uid, gid_t file_gid,
-    struct acl *aclp, mode_t acc_mode, struct ucred *cred, int *privused)
+/*
+ * Return 1, if access is explicitly denied, -1, if its implicitly
+ * denied (not allowed), or 0, if allowed.
+ *
+ * XXX: There just cannot be a worse name than this one.
+ */
+static int
+_match_acl(const struct acl *aclp, int needed_bits, struct ucred *cred,
+    int file_uid, int file_gid)
 {
-	int i, needed_bits = 0;
-	struct acl_entry *entry;
-	mode_t priv_granted = 0;
-
-	if (privused != NULL)
-		*privused = 0;
-
-	if (acc_mode & VREAD)
-		needed_bits |= ACL_READ_DATA;
-
-	if (acc_mode & VWRITE)
-		needed_bits |= ACL_WRITE_DATA;
-
-	if (acc_mode & VAPPEND)
-		needed_bits |= ACL_APPEND_DATA;
-
-	if (acc_mode & VEXEC)
-		needed_bits |= ACL_EXECUTE;
-
-	if (acc_mode & VADMIN)
-		needed_bits |= (ACL_WRITE_NAMED_ATTRS | ACL_WRITE_ATTRIBUTES |
-		    ACL_WRITE_ACL | ACL_WRITE_OWNER);
+	int i;
+	const struct acl_entry *entry;
 
 	for (i = 0; i < aclp->acl_cnt; i++) {
 		entry = &(aclp->acl_entry[i]);
@@ -104,7 +132,7 @@
 				continue;
 
 			if (_match_bits(entry, &needed_bits))
-				goto explicitly_denied;
+				return (1);
 			if (needed_bits == 0)
 				return (0);
 
@@ -115,7 +143,7 @@
 				continue;
 
 			if (_match_bits(entry, &needed_bits))
-				goto explicitly_denied;
+				return (1);
 			if (needed_bits == 0)
 				return (0);
 
@@ -126,7 +154,7 @@
 				continue;
 
 			if (_match_bits(entry, &needed_bits))
-				goto explicitly_denied;
+				return (1);
 			if (needed_bits == 0)
 				return (0);
 
@@ -137,7 +165,7 @@
 				continue;
 
 			if (_match_bits(entry, &needed_bits))
-				goto explicitly_denied;
+				return (1);
 			if (needed_bits == 0)
 				return (0);
 
@@ -148,19 +176,63 @@
 			    "entry->ae_tag == ACL_EVERYONE");
 
 			if (_match_bits(entry, &needed_bits))
-				goto explicitly_denied;
+				return (1);
 			if (needed_bits == 0)
 				return (0);
 		}
 	}
 
-explicitly_denied:
+	return (-1);
+}
+
+int
+vaccess_acl_nfs4(enum vtype type, uid_t file_uid, gid_t file_gid,
+    struct acl *aclp, mode_t acc_mode, int needed_bits, struct ucred *cred,
+    int *privused)
+{
+	mode_t priv_granted = 0;
+	int denied, is_directory;
+
+	if (privused != NULL)
+		*privused = 0;
+
+	if (needed_bits == 0)
+		needed_bits = _access_mask_from_mode(acc_mode);
+
+	if (type == VDIR)
+		is_directory = 1;
+	else
+		is_directory = 0;
+
+	/*
+	 * File owner is always allowed to read and write the ACL.
+	 */
+	if (file_uid == cred->cr_uid)
+		needed_bits &= ~(ACL_READ_ACL | ACL_WRITE_ACL);
+
+	denied = _match_acl(aclp, needed_bits, cred, file_uid, file_gid);
+	if (!denied)
+		return (0);
+
+	/*
+	 * If we want to append data to the file, either one of ACL_APPEND_DATA
+	 * or ACL_WRITE_DATA is sufficient.  We just tested for the former
+	 * and we were denied access.  Let's try with the latter.
+	 */ 
+	if ((needed_bits & ACL_APPEND_DATA) && !is_directory) {
+		needed_bits |= ACL_WRITE_DATA;
+		needed_bits &= ~ACL_APPEND_DATA;
+
+		denied = _match_acl(aclp, needed_bits, cred, file_uid, file_gid);
+		if (!denied)
+			return (0);
+	}
 
 	/*
 	 * No match.  Try to use privileges, if there are any.
 	 * Taken from kern/subr_acl_posix1e.c.
 	 */
-	if (type == VDIR) {
+	if (is_directory) {
 		if ((acc_mode & VEXEC) && !priv_check_cred(cred,
 		    PRIV_VFS_LOOKUP, 0))
 			priv_granted |= VEXEC;
@@ -180,6 +252,9 @@
 	if ((acc_mode & VADMIN) && !priv_check_cred(cred, PRIV_VFS_ADMIN, 0))
 		priv_granted |= VADMIN;
 
+	if (priv_granted != 0)
+		priv_granted |= VSTAT;
+
 	if ((acc_mode & priv_granted) == acc_mode) {
 		if (privused != NULL)
 			*privused = 1;
@@ -297,7 +372,8 @@
 		    (ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT)) {
 			/*
 			 * 1.3.1. A copy of the current ACE is made, and placed
-			 *        in the ACL immediately following the current ACE.
+			 *        in the ACL immediately following the current
+			 *        ACE.
 			 */
 			copy = _acl_duplicate_entry(aclp, i);
 			/* XXX: Is EPERM a good choice here? */
@@ -305,13 +381,16 @@
 				return (EPERM);
 
 			/*
-			 * 1.3.2. In the first ACE, the flag ACL_ENTRY_ONLY_INHERIT is set.
+			 * 1.3.2. In the first ACE, the flag
+			 *        ACL_ENTRY_ONLY_INHERIT is set.
 			 */
 			entry->ae_flags |= ACL_ENTRY_ONLY_INHERIT;
 
 			/*
-			 * 1.3.3. In the second ACE, the following flags are cleared:
-			 *        ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT,
+			 * 1.3.3. In the second ACE, the following flags
+			 *        are cleared:
+			 *        ACL_ENTRY_FILE_INHERIT,
+			 *        ACL_ENTRY_DIRECTORY_INHERIT,
 			 *        ACL_ENTRY_LIMIT_INHERIT.
 			 */
 			copy->ae_flags &= ~(ACL_ENTRY_FILE_INHERIT |
@@ -325,11 +404,12 @@
 		}
 
 		/*
-		 * 1.4. If it's owner@, group@ or everyone@ entry, clear ACL_READ_DATA,
-		 *      ACL_WRITE_DATA, ACL_APPEND_DATA and ACL_EXECUTE.  Continue
-		 *      to the next entry.
+		 * 1.4. If it's owner@, group@ or everyone@ entry, clear
+		 *      ACL_READ_DATA, ACL_WRITE_DATA, ACL_APPEND_DATA
+		 *      and ACL_EXECUTE.  Continue to the next entry.
 		 */
-		if (entry->ae_tag == ACL_USER_OBJ || entry->ae_tag == ACL_GROUP_OBJ ||
+		if (entry->ae_tag == ACL_USER_OBJ ||
+		    entry->ae_tag == ACL_GROUP_OBJ ||
 		    entry->ae_tag == ACL_EVERYONE) {
 			entry->ae_perm &= ~(ACL_READ_DATA | ACL_WRITE_DATA |
 			    ACL_APPEND_DATA | ACL_EXECUTE);
@@ -337,11 +417,11 @@
 		}
 
 		/*
-		 * 1.5. Otherwise, if the "who" field did not match one of OWNER@,
-		 *      GROUP@, EVERYONE@:
+		 * 1.5. Otherwise, if the "who" field did not match one
+		 *      of OWNER@, GROUP@, EVERYONE@:
 		 *
-		 * 1.5.1. If the type is ALLOW, check the preceding ACE.  If it does
-		 *        not meet all of the following criteria:
+		 * 1.5.1. If the type is ALLOW, check the preceding ACE.
+		 *        If it does not meet all of the following criteria:
 		 */
 		if (entry->ae_extended != ACL_EXTENDED_ALLOW)
 			continue;
@@ -358,16 +438,17 @@
 				meets = 0;
 
 			/*
-			 * 1.5.1.2. The "who" field is the same as the current ACE,
+			 * 1.5.1.2. The "who" field is the same as the current
+			 *          ACE,
 			 */
 			if (previous->ae_id != entry->ae_id ||
 			    previous->ae_tag != entry->ae_tag)
 				meets = 0;
 
 			/*
-			 * 1.5.1.3. The flag bit ACE4_IDENTIFIER_GROUP is the same
-			 *          as it is in the current ACE, and no other flag
-			 *          bits are set,
+			 * 1.5.1.3. The flag bit ACE4_IDENTIFIER_GROUP
+			 *          is the same as it is in the current ACE,
+			 *          and no other flag bits are set,
 			 */
 			if ((previous->ae_tag == ACL_GROUP) !=
 			    (entry->ae_tag == ACL_GROUP))
@@ -379,23 +460,23 @@
 			/*
 			 * 1.5.1.4. The mask bits are a subset of the mask bits
 			 *          of the current ACE, and are also subset of
-			 *          the following: ACL_READ_DATA, ACL_WRITE_DATA,
-			 *          ACL_APPEND_DATA, ACL_EXECUTE
+			 *          the following: ACL_READ_DATA,
+			 *          ACL_WRITE_DATA, ACL_APPEND_DATA, ACL_EXECUTE
 			 */
 			if (previous->ae_perm & ~(entry->ae_perm))
 				meets = 0;
 
-			if (previous->ae_perm & ~(ACL_READ_DATA | ACL_WRITE_DATA |
-			    ACL_APPEND_DATA | ACL_EXECUTE))
+			if (previous->ae_perm & ~(ACL_READ_DATA |
+			    ACL_WRITE_DATA | ACL_APPEND_DATA | ACL_EXECUTE))
 				meets = 0;
 		}
 
 		if (!meets) {
 			/*
-		 	 * Then the ACE of type DENY, with a who equal to the current
-			 * ACE, flag bits equal to
-			 * (<current ACE flags> & <ACE_IDENTIFIER_GROUP) and no mask
-			 * bits, is prepended.
+		 	 * Then the ACE of type DENY, with a who equal
+			 * to the current ACE, flag bits equal to
+			 * (<current ACE flags> & <ACE_IDENTIFIER_GROUP>)
+			 * and no mask bits, is prepended.
 			 */
 			previous = entry;
 			entry = _acl_duplicate_entry(aclp, i);
@@ -460,6 +541,8 @@
 		/*
 		 * 1.5.3. If ACE4_IDENTIFIER_GROUP is set in the flags
 		 *        of the ALLOW ace:
+		 *
+		 * XXX: This point is not there in the Falkner's draft.
 		 */
 		if (entry->ae_tag == ACL_GROUP &&
 		    entry->ae_extended == ACL_EXTENDED_ALLOW) {
@@ -514,20 +597,22 @@
 		    ACL_EXTENDED_DENY))
 			must_append = 1;
 		if (_entry_does_not_match(a2, ACL_USER_OBJ, ACL_WRITE_ACL |
-		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | ACL_WRITE_NAMED_ATTRS,
-		    ACL_EXTENDED_ALLOW))
+		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
+		    ACL_WRITE_NAMED_ATTRS, ACL_EXTENDED_ALLOW))
 			must_append = 1;
-		if (_entry_does_not_match(a3, ACL_GROUP_OBJ, 0, ACL_EXTENDED_DENY))
+		if (_entry_does_not_match(a3, ACL_GROUP_OBJ, 0,
+		    ACL_EXTENDED_DENY))
 			must_append = 1;
-		if (_entry_does_not_match(a4, ACL_GROUP_OBJ, 0, ACL_EXTENDED_ALLOW))
+		if (_entry_does_not_match(a4, ACL_GROUP_OBJ, 0,
+		    ACL_EXTENDED_ALLOW))
 			must_append = 1;
 		if (_entry_does_not_match(a5, ACL_EVERYONE, ACL_WRITE_ACL |
-		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | ACL_WRITE_NAMED_ATTRS,
-		    ACL_EXTENDED_DENY))
+		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
+		    ACL_WRITE_NAMED_ATTRS, ACL_EXTENDED_DENY))
 			must_append = 1;
 		if (_entry_does_not_match(a6, ACL_EVERYONE, ACL_READ_ACL |
-		    ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS | ACL_SYNCHRONIZE,
-		    ACL_EXTENDED_ALLOW))
+		    ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS |
+		    ACL_SYNCHRONIZE, ACL_EXTENDED_ALLOW))
 			must_append = 1;
 	}
 
@@ -536,15 +621,17 @@
 			return (EPERM);
 
 		a1 = _acl_append(aclp, ACL_USER_OBJ, 0, ACL_EXTENDED_DENY);
-		a2 = _acl_append(aclp, ACL_USER_OBJ, ACL_WRITE_ACL | ACL_WRITE_OWNER |
-		    ACL_WRITE_ATTRIBUTES | ACL_WRITE_NAMED_ATTRS, ACL_EXTENDED_ALLOW);
+		a2 = _acl_append(aclp, ACL_USER_OBJ, ACL_WRITE_ACL |
+		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
+		    ACL_WRITE_NAMED_ATTRS, ACL_EXTENDED_ALLOW);
 		a3 = _acl_append(aclp, ACL_GROUP_OBJ, 0, ACL_EXTENDED_DENY);
 		a4 = _acl_append(aclp, ACL_GROUP_OBJ, 0, ACL_EXTENDED_ALLOW);
-		a5 = _acl_append(aclp, ACL_EVERYONE, ACL_WRITE_ACL | ACL_WRITE_OWNER |
-		    ACL_WRITE_ATTRIBUTES | ACL_WRITE_NAMED_ATTRS, ACL_EXTENDED_DENY);
+		a5 = _acl_append(aclp, ACL_EVERYONE, ACL_WRITE_ACL |
+		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
+		    ACL_WRITE_NAMED_ATTRS, ACL_EXTENDED_DENY);
 		a6 = _acl_append(aclp, ACL_EVERYONE, ACL_READ_ACL |
-		    ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS | ACL_SYNCHRONIZE,
-		    ACL_EXTENDED_ALLOW);
+		    ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS |
+		    ACL_SYNCHRONIZE, ACL_EXTENDED_ALLOW);
 
 		KASSERT(a1 != NULL && a2 != NULL && a3 != NULL && a4 != NULL &&
 		    a5 != NULL && a6 != NULL, "couldn't append to ACL.");
@@ -768,7 +855,7 @@
 	}
 
 	/*
-	 * 2. For each entry in the new ACL, adjust it's flags, possibly
+	 * 2. For each entry in the new ACL, adjust its flags, possibly
 	 *    creating two entries in place of one.
 	 */
 	for (i = 0; i < child_aclp->acl_cnt; i++) {
@@ -781,7 +868,8 @@
 		 *      ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT,
 		 *      ACL_ENTRY_ONLY_INHERIT.
 		 */
-		if (entry->ae_flags & ACL_ENTRY_LIMIT_INHERIT || !is_directory) {
+		if (entry->ae_flags & ACL_ENTRY_LIMIT_INHERIT ||
+		    !is_directory) {
 			entry->ae_flags &= ~(ACL_ENTRY_LIMIT_INHERIT |
 			ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT |
 			ACL_ENTRY_ONLY_INHERIT);
@@ -802,7 +890,8 @@
 		 * XXX: Read it again and make sure what does the "otherwise"
 		 *      apply to.
 		 */
-		if (is_directory && (entry->ae_flags & ACL_ENTRY_FILE_INHERIT) &&
+		if (is_directory &&
+		    (entry->ae_flags & ACL_ENTRY_FILE_INHERIT) &&
 		    ((entry->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0)) {
 			entry->ae_flags |= ACL_ENTRY_ONLY_INHERIT;
 			continue;
@@ -927,6 +1016,11 @@
 		if ((entry->ae_flags | ACL_FLAGS_BITS) != ACL_FLAGS_BITS)
 			return (EINVAL);
 
+		/* Disallow unimplemented flags. */
+		if (entry->ae_flags & (ACL_ENTRY_SUCCESSFUL_ACCESS |
+		    ACL_ENTRY_FAILED_ACCESS | ACL_ENTRY_INHERITED))
+			return (EINVAL);
+
 		/* Disallow flags not allowed for ordinary files. */
 		if (!is_directory) {
 			if (entry->ae_flags & (ACL_ENTRY_FILE_INHERIT |

==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/subr_acl_posix1e.c#3 (text+ko) ====

@@ -71,6 +71,9 @@
 	if (privused != NULL)
 		*privused = 0;
 
+	if (acc_mode == VSTAT)
+		return (0);
+
 	/*
 	 * Determine privileges now, but don't apply until we've found a DAC
 	 * entry that matches but has failed to allow access.

==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_default.c#2 (text+ko) ====

@@ -83,6 +83,7 @@
 	.vop_fsync =		VOP_NULL,
 	.vop_getpages =		vop_stdgetpages,
 	.vop_getwritemount = 	vop_stdgetwritemount,
+	.vop_granular =		vop_stdgranular,
 	.vop_inactive =		VOP_NULL,
 	.vop_ioctl =		VOP_ENOTTY,
 	.vop_kqfilter =		vop_stdkqfilter,
@@ -509,6 +510,19 @@
 
 	return (error);
 }
+         
+int
+vop_stdgranular(ap)
+	struct vop_granular_args /* {
+		struct vnode *a_vp;
+		int  a_mode;
+		int  a_access_mask;
+		struct ucred *a_cred;
+		struct thread *a_td;
+	} */ *ap;
+{
+	return (VOP_ACCESS(ap->a_vp, ap->a_mode, ap->a_cred, ap->a_td));
+}
 
 /* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */
 int

==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_subr.c#3 (text+ko) ====

@@ -3458,6 +3458,9 @@
 
 	dac_granted = 0;
 
+	if (acc_mode == VSTAT)
+		return (0);
+
 	/* Check the owner. */
 	if (cred->cr_uid == file_uid) {
 		dac_granted |= VADMIN;
@@ -3568,6 +3571,15 @@
 		/* Potentially should be: return (EPERM); */
 		return (priv_check_cred(cred, PRIV_VFS_EXTATTR_SYSTEM, 0));
 	case EXTATTR_NAMESPACE_USER:
+#ifdef SunOS_doesnt_do_that
+		if (access == VREAD)
+			return (VOP_GRANULAR(vp, access, ACL_READ_NAMED_ATTRS,
+			   cred, td));
+		if (access == VWRITE)
+			return (VOP_GRANULAR(vp, access, ACL_WRITE_NAMED_ATTRS,
+			   cred, td));
+#endif
+		/* XXX: Is this possible for "access" to not be any of the two above? */
 		return (VOP_ACCESS(vp, access, cred, td));
 	default:
 		return (EPERM);

==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_vnops.c#2 (text+ko) ====

@@ -701,6 +701,9 @@
 	if (error)
 		return (error);
 #endif
+	error = VOP_GRANULAR(vp, VSTAT, ACL_READ_ATTRIBUTES, active_cred, td);
+	if (error)
+		return (error);
 
 	vap = &vattr;
 	error = VOP_GETATTR(vp, vap, active_cred, td);

==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vnode_if.src#4 (text+ko) ====

@@ -153,6 +153,17 @@
 };
 
 
+%% granular	vp	L L L
+
+vop_granular {
+	IN struct vnode *vp;
+	IN int mode;
+	IN int access_mask;
+	IN struct ucred *cred;
+	IN struct thread *td;
+};
+
+
 %% getattr	vp	L L L
 
 vop_getattr {

==== //depot/projects/soc2008/trasz_nfs4acl/sys/sys/acl.h#11 (text+ko) ====

@@ -175,10 +175,8 @@
 #define ACL_WRITE_EXTATTRIBUTES	ACL_WRITE_NAMED_ATTRS /* Darwin compatibility. */
 #ifdef XXX_conflicting_defines
 #define ACL_EXECUTE		0x00200000
+#endif
 #define ACL_SEARCH		ACL_EXECUTE /* Darwin compatibility. */
-#else
-#define ACL_SEARCH		0x00200000
-#endif
 #define ACL_DELETE_CHILD	0x00400000
 #define ACL_READ_ATTRIBUTES	0x00800000
 #define ACL_WRITE_ATTRIBUTES	0x01000000
@@ -205,18 +203,23 @@
 /*
  * Possible values in ae_flags field; valid only for NFSv4 ACLs.
  */
-/* #define ACL_FLAG_DEFER_INHERIT - this doesn't seem to be used in Darwin. */
-/* #define ACL_ENTRY_INHERITED - this seems to be used in Darwin, but how does it translate into rfc3530? */
-#define ACL_ENTRY_FILE_INHERIT		0x00000001 /* ACE4_FILE_INHERIT_ACE */
-#define ACL_ENTRY_DIRECTORY_INHERIT	0x00000002 /* ACE4_DIRECTORY_INHERIT_ACE */
-#define ACL_ENTRY_LIMIT_INHERIT		0x00000004 /* ACE4_NO_PROPAGATE_INHERIT_ACE */
-#define ACL_ENTRY_ONLY_INHERIT		0x00000008 /* ACE4_INHERIT_ONLY_ACE */
-#define ACL_FLAG_SUCCESSFUL_ACCESS	0x00000010 /* Valid only for ACL_EXTENDED_ALARM and ACL_EXTENDED_AUDIT. */
-#define ACL_FLAG_FAILED_ACCESS		0x00000020 /* s/a */
+/*
+ * ACL_FLAG_DEFER_INHERIT does not seem to be used anywhere in Darwin,
+ * and there is no such flag in NFSv4 spec.
+ *
+ * #define ACL_FLAG_DEFER_INHERIT
+ */
+#define ACL_ENTRY_FILE_INHERIT		0x00000001
+#define ACL_ENTRY_DIRECTORY_INHERIT	0x00000002
+#define ACL_ENTRY_LIMIT_INHERIT		0x00000004 /* NO_PROPAGATE_INHERIT */
+#define ACL_ENTRY_ONLY_INHERIT		0x00000008 /* INHERIT_ONLY */
+#define ACL_ENTRY_SUCCESSFUL_ACCESS	0x00000010
+#define ACL_ENTRY_FAILED_ACCESS		0x00000020
+#define ACL_ENTRY_INHERITED		0x00000080 /* Currently unused. */
 
 #define ACL_FLAGS_BITS (ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | \
-    ACL_ENTRY_LIMIT_INHERIT | ACL_ENTRY_ONLY_INHERIT | ACL_FLAG_SUCCESSFUL_ACCESS | \
-    ACL_FLAG_FAILED_ACCESS)
+    ACL_ENTRY_LIMIT_INHERIT | ACL_ENTRY_ONLY_INHERIT | ACL_ENTRY_SUCCESSFUL_ACCESS | \
+    ACL_ENTRY_FAILED_ACCESS)
 
 /*
  * Undefined value in ae_id field

==== //depot/projects/soc2008/trasz_nfs4acl/sys/sys/vnode.h#3 (text+ko) ====

@@ -591,7 +591,7 @@
 	    struct ucred *cred, int *privused);
 int	vaccess_acl_nfs4(enum vtype type, uid_t file_uid,
 	    gid_t file_gid, struct acl *acl, mode_t acc_mode,
-	    struct ucred *cred, int *privused);
+	    int access_mask, struct ucred *cred, int *privused);
 void	vattr_null(struct vattr *vap);
 int	vcount(struct vnode *vp);
 void	vdrop(struct vnode *);
@@ -648,6 +648,7 @@
 int	vop_stdbmap(struct vop_bmap_args *);
 int	vop_stdfsync(struct vop_fsync_args *);
 int	vop_stdgetwritemount(struct vop_getwritemount_args *);
+int	vop_stdgranular(struct vop_granular_args *);
 int	vop_stdgetpages(struct vop_getpages_args *);
 int	vop_stdinactive(struct vop_inactive_args *);
 int	vop_stdislocked(struct vop_islocked_args *);

==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ffs/ffs_vnops.c#2 (text+ko) ====

@@ -1409,7 +1409,7 @@
 		return (EROFS);
 
 	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
-	    ap->a_cred, ap->a_td, IWRITE);
+	    ap->a_cred, ap->a_td, VWRITE);
 	if (error) {
 		if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
 			ip->i_ea_error = error;
@@ -1493,7 +1493,7 @@
 		return (EOPNOTSUPP);
 
 	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
-	    ap->a_cred, ap->a_td, IREAD);
+	    ap->a_cred, ap->a_td, VREAD);
 	if (error)
 		return (error);
 
@@ -1553,7 +1553,7 @@
 		return (EOPNOTSUPP);
 
 	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
-	    ap->a_cred, ap->a_td, IREAD);
+	    ap->a_cred, ap->a_td, VREAD);
 	if (error)
 		return (error);
 
@@ -1633,7 +1633,7 @@
 		return (EROFS);
 
 	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
-	    ap->a_cred, ap->a_td, IWRITE);
+	    ap->a_cred, ap->a_td, VWRITE);
 	if (error) {
 		if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
 			ip->i_ea_error = error;

==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_acl.c#6 (text+ko) ====

@@ -380,7 +380,7 @@
 	/*
 	 * Must hold VADMIN (be file owner) or have appropriate privilege.
 	 */
-	if ((error = VOP_ACCESS(ap->a_vp, VADMIN, ap->a_cred, ap->a_td)))
+	if ((error = VOP_GRANULAR(ap->a_vp, VADMIN, ACL_WRITE_ACL, ap->a_cred, ap->a_td)))
 		return (error);
 
 	if (acl_nfs4_is_trivial(ap->a_aclp)) {

==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_extattr.c#2 (text+ko) ====

@@ -847,7 +847,7 @@
 	if (strlen(name) == 0)
 		return (EINVAL);
 
-	error = extattr_check_cred(vp, attrnamespace, cred, td, IREAD);
+	error = extattr_check_cred(vp, attrnamespace, cred, td, VREAD);
 	if (error)
 		return (error);
 
@@ -1054,7 +1054,7 @@
 	if (!ufs_extattr_valid_attrname(attrnamespace, name))
 		return (EINVAL);
 
-	error = extattr_check_cred(vp, attrnamespace, cred, td, IWRITE);
+	error = extattr_check_cred(vp, attrnamespace, cred, td, VWRITE);
 	if (error)
 		return (error);
 
@@ -1162,7 +1162,7 @@
 	if (!ufs_extattr_valid_attrname(attrnamespace, name))
 		return (EINVAL);
 
-	error = extattr_check_cred(vp, attrnamespace, cred, td, IWRITE);
+	error = extattr_check_cred(vp, attrnamespace, cred, td, VWRITE);
 	if (error)
 		return (error);
 

==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_vnops.c#6 (text+ko) ====

@@ -96,6 +96,7 @@
 static vop_close_t	ufs_close;
 static vop_create_t	ufs_create;
 static vop_getattr_t	ufs_getattr;
+static vop_granular_t	ufs_granular;
 static vop_link_t	ufs_link;
 static int ufs_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
 static vop_mkdir_t	ufs_mkdir;
@@ -298,10 +299,11 @@
 }
 
 static int
-ufs_access(ap)
-	struct vop_access_args /* {
+ufs_granular(ap)
+	struct vop_granular_args /* {
 		struct vnode *a_vp;
 		int  a_mode;
+		int  a_access_mask;
 		struct ucred *a_cred;
 		struct thread *a_td;
 	} */ *ap;
@@ -355,7 +357,8 @@
 		case 0:
 			if (type == ACL_TYPE_NFS4) {
 				error = vaccess_acl_nfs4(vp->v_type, ip->i_uid,
-				    ip->i_gid, acl, ap->a_mode, ap->a_cred, NULL);
+				    ip->i_gid, acl, ap->a_mode,
+				    ap->a_access_mask, ap->a_cred, NULL);
 			} else {
 				error = vaccess_acl_posix1e(vp->v_type, ip->i_uid,
 				    ip->i_gid, acl, ap->a_mode, ap->a_cred, NULL);
@@ -381,6 +384,18 @@
 	return (error);
 }
 
+static int
+ufs_access(ap)
+	struct vop_access_args /* {
+		struct vnode *a_vp;
+		int  a_mode;
+		struct ucred *a_cred;
+		struct thread *a_td;
+	} */ *ap;
+{
+	return (VOP_GRANULAR(ap->a_vp, ap->a_mode, 0, ap->a_cred, ap->a_td));
+}
+
 /* ARGSUSED */
 static int
 ufs_getattr(ap)
@@ -598,11 +613,24 @@
 		 * check succeeds.
 		 */
 		if (vap->va_vaflags & VA_UTIMES_NULL) {
-			error = VOP_ACCESS(vp, VADMIN, cred, td);
+			/*
+			 * NFSv4.1, draft 21, 6.2.1.3.1, Discussion of Mask Attributes
+			 *
+			 * "A user having ACL_WRITE_DATA or ACL_WRITE_ATTRIBUTES
+			 * will be allowed to set the times [..] to the current
+			 * server time."
+			 *
+			 * XXX: Calling it four times seems a little excessive.
+			 */
+			error = VOP_GRANULAR(vp, VADMIN, ACL_WRITE_DATA, cred, td);
+			if (error)
+				error = VOP_GRANULAR(vp, VADMIN, ACL_WRITE_ATTRIBUTES, cred, td);
+			if (error)
+				error = VOP_GRANULAR(vp, VWRITE, ACL_WRITE_DATA, cred, td);
 			if (error)
-				error = VOP_ACCESS(vp, VWRITE, cred, td);
+				error = VOP_GRANULAR(vp, VWRITE, ACL_WRITE_ATTRIBUTES, cred, td);
 		} else
-			error = VOP_ACCESS(vp, VADMIN, cred, td);
+			error = VOP_GRANULAR(vp, VADMIN, ACL_WRITE_ATTRIBUTES, cred, td);
 		if (error)
 			return (error);
 		if (vap->va_atime.tv_sec != VNOVAL)
@@ -691,7 +719,7 @@
 	 * To modify the permissions on a file, must possess VADMIN
 	 * for that file.
 	 */
-	if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
+	if ((error = VOP_GRANULAR(vp, VADMIN, ACL_WRITE_ACL, cred, td)))
 		return (error);
 	/*
 	 * Privileged processes may set the sticky bit on non-directories,
@@ -748,7 +776,7 @@
 	 * To modify the ownership of a file, must possess VADMIN for that
 	 * file.
 	 */
-	if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
+	if ((error = VOP_GRANULAR(vp, VADMIN, ACL_WRITE_OWNER, cred, td)))
 		return (error);
 	/*
 	 * To change the owner of a file, or change the group of a file to a
@@ -2538,6 +2566,7 @@
 	.vop_close =		ufs_close,
 	.vop_create =		ufs_create,
 	.vop_getattr =		ufs_getattr,
+	.vop_granular =		ufs_granular,
 	.vop_inactive =		ufs_inactive,
 	.vop_link =		ufs_link,
 	.vop_lookup =		vfs_cache_lookup,
@@ -2578,6 +2607,7 @@
 	.vop_access =		ufs_access,
 	.vop_close =		ufsfifo_close,
 	.vop_getattr =		ufs_getattr,
+	.vop_granular =		ufs_granular,
 	.vop_inactive =		ufs_inactive,
 	.vop_kqfilter =		ufsfifo_kqfilter,
 	.vop_print =		ufs_print,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807081219.m68CJwCT035698>