PERFORCE change 144877 for review
Edward Tomasz Napierala
trasz at FreeBSD.org
Tue Jul 8 12:19:59 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=144877
Change 144877 by trasz at 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,
More information about the p4-projects
mailing list