PERFORCE change 146156 for review
Edward Tomasz Napierala
trasz at FreeBSD.org
Mon Jul 28 20:31:08 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=146156
Change 146156 by trasz at trasz_traszkan on 2008/07/28 20:30:29
Implement ACL_DELETE and ACL_DELETE_CHILD.
Note - it should be reviewed by someone who understands ufs_lookup().
Affected files ...
.. //depot/projects/soc2008/trasz_nfs4acl/TODO#17 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/subr_acl_nfs4.c#10 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/sys/vnode.h#4 edit
.. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_lookup.c#6 edit
Differences ...
==== //depot/projects/soc2008/trasz_nfs4acl/TODO#17 (text+ko) ====
@@ -22,26 +22,6 @@
acl_set_extended_np, acl_set_flagset_np, acl_to_text_np, acl_is_trivial_np,
acl_strip_np.
-- Make access control more granular. The following are done:
-
- ACL_READ_DATA
- ACL_WRITE_DATA
- ACL_APPEND_DATA
- ACL_EXECUTE
- ACL_READ_ATTRIBUTES
- ACL_WRITE_ATTRIBUTES
- ACL_READ_NAMED_ATTRS (implemented, #ifdefed out for SunOS compatibility)
- ACL_WRITE_NAMED_ATTRS (implemented, #ifdefed out for SunOS compatibility)
- ACL_READ_ACL
- ACL_WRITE_ACL
- ACL_WRITE_OWNER
- ACL_SYNCHRONIZE (not used)
-
- The following are left:
-
- ACL_DELETE_CHILD
- ACL_DELETE
-
- Add granular access control to ZFS.
- Write code to do the same operations on UFS and ZFS and compare results.
==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/subr_acl_nfs4.c#10 (text+ko) ====
@@ -88,18 +88,19 @@
}
/*
- * Return 1, if access is explicitly denied, -1, if its implicitly
- * denied (not allowed), or 0, if allowed.
+ * Return 0, iff access is allowed, 1 otherwise.
*
- * 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)
+_acl_denies(const struct acl *aclp, int needed_bits, struct ucred *cred,
+ int file_uid, int file_gid, int *denied_explicitly)
{
int i;
const struct acl_entry *entry;
+ if (denied_explicitly)
+ *denied_explicitly = 0;
+
for (i = 0; i < aclp->acl_cnt; i++) {
entry = &(aclp->acl_entry[i]);
@@ -134,8 +135,12 @@
}
if (entry->ae_extended == ACL_EXTENDED_DENY) {
- if (entry->ae_perm & needed_bits)
+ if (entry->ae_perm & needed_bits) {
+ if (denied_explicitly)
+ *denied_explicitly = 1;
+
return (1);
+ }
}
needed_bits &= ~(entry->ae_perm);
@@ -144,7 +149,7 @@
return (0);
}
- return (-1);
+ return (1);
}
int
@@ -153,7 +158,7 @@
int *privused)
{
mode_t priv_granted = 0;
- int denied, is_directory;
+ int denied, explicitly_denied, is_directory;
if (privused != NULL)
*privused = 0;
@@ -174,10 +179,16 @@
needed_bits &= ~(ACL_READ_ACL | ACL_WRITE_ACL |
ACL_READ_ATTRIBUTES | ACL_WRITE_ATTRIBUTES);
- denied = _match_acl(aclp, needed_bits, cred, file_uid, file_gid);
+ denied = _acl_denies(aclp, needed_bits, cred, file_uid, file_gid,
+ &explicitly_denied);
if (!denied)
return (0);
+ if ((acc_mode & VEXPLICIT_DENY) && explicitly_denied == 0)
+ return (0);
+
+ acc_mode &= ~VEXPLICIT_DENY;
+
/*
* 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
@@ -187,7 +198,8 @@
needed_bits |= ACL_WRITE_DATA;
needed_bits &= ~ACL_APPEND_DATA;
- denied = _match_acl(aclp, needed_bits, cred, file_uid, file_gid);
+ denied = _acl_denies(aclp, needed_bits, cred, file_uid,
+ file_gid, NULL);
if (!denied)
return (0);
}
==== //depot/projects/soc2008/trasz_nfs4acl/sys/sys/vnode.h#4 (text+ko) ====
@@ -310,15 +310,16 @@
/*
* Modes. Some values same as Ixxx entries from inode.h for now.
*/
-#define VEXEC 000100 /* execute/search permission */
-#define VWRITE 000200 /* write permission */
-#define VREAD 000400 /* read permission */
-#define VSVTX 001000 /* save swapped text even after use */
-#define VSGID 002000 /* set group id on execution */
-#define VSUID 004000 /* set user id on execution */
-#define VADMIN 010000 /* permission to administer */
-#define VSTAT 020000 /* permission to retrieve attrs */
-#define VAPPEND 040000 /* permission to write/append */
+#define VEXEC 0000100 /* execute/search permission */
+#define VWRITE 0000200 /* write permission */
+#define VREAD 0000400 /* read permission */
+#define VSVTX 0001000 /* save swapped text even after use */
+#define VSGID 0002000 /* set group id on execution */
+#define VSUID 0004000 /* set user id on execution */
+#define VADMIN 0010000 /* permission to administer */
+#define VSTAT 0020000 /* permission to retrieve attrs */
+#define VAPPEND 0040000 /* permission to write/append */
+#define VEXPLICIT_DENY 0100000 /* return EPERM only if permission was denied explicitly */
#define VALLPERM (VEXEC | VWRITE | VREAD | VADMIN | VSTAT | VAPPEND)
/*
==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_lookup.c#6 (text+ko) ====
@@ -77,6 +77,59 @@
/* true if old FS format...*/
#define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0)
+static int
+ufs_delete_denied(struct vnode *vdp, struct vnode *tdp, struct ucred *cred,
+ struct thread *td)
+{
+ int error;
+
+ /*
+ * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt
+ *
+ * 3.16.2.1. ACE4_DELETE vs. ACE4_DELETE_CHILD
+ */
+
+ /*
+ * XXX: Is this check required?
+ */
+ error = VOP_GRANULAR(vdp, VEXEC, ACL_EXECUTE, cred, td);
+ if (error)
+ return (error);
+
+ error = VOP_GRANULAR(tdp, VADMIN, ACL_DELETE, cred, td);
+ if (error == 0)
+ return (0);
+
+ error = VOP_GRANULAR(vdp, VWRITE, ACL_DELETE_CHILD, cred, td);
+ if (error == 0)
+ return (0);
+
+ error = VOP_GRANULAR(vdp, VWRITE | VEXPLICIT_DENY, ACL_DELETE_CHILD,
+ cred, td);
+ if (error)
+ return (error);
+
+ /*
+ * Standard Unix access control - delete access requires VWRITE.
+ */
+ error = VOP_GRANULAR(vdp, VWRITE, ACL_WRITE_DATA, cred, td);
+ if (error)
+ return (error);
+
+ /*
+ * If directory is "sticky", then user must own
+ * the directory, or the file in it, else she
+ * may not delete it (unless she's root). This
+ * implements append-only directories.
+ */
+ if ((VTOI(vdp)->i_mode & ISVTX) &&
+ VOP_ACCESS(vdp, VADMIN, cred, td) &&
+ VOP_ACCESS(tdp, VADMIN, cred, td))
+ return (EPERM);
+
+ return (0);
+}
+
/*
* Convert a component of a pathname into a pointer to a locked inode.
* This is a very central and rather complicated routine.
@@ -495,12 +548,17 @@
*/
if (nameiop == DELETE && (flags & ISLASTCN)) {
ASSERT_VOP_ELOCKED(vdp, __FUNCTION__);
- /*
- * Write access to directory required to delete files.
- */
- error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread);
- if (error)
+ if ((error = VFS_VGET(vdp->v_mount, ino,
+ LK_EXCLUSIVE, &tdp)) != 0)
+ return (error);
+
+ error = ufs_delete_denied(vdp, tdp, cred, cnp->cn_thread);
+ if (error) {
+ vput(tdp);
return (error);
+ }
+
+
/*
* Return pointer to current entry in dp->i_offset,
* and distance past previous entry (if there
@@ -514,23 +572,10 @@
if (dp->i_number == ino) {
VREF(vdp);
*vpp = vdp;
+ vput(tdp);
return (0);
}
- if ((error = VFS_VGET(vdp->v_mount, ino,
- LK_EXCLUSIVE, &tdp)) != 0)
- return (error);
- /*
- * If directory is "sticky", then user must own
- * the directory, or the file in it, else she
- * may not delete it (unless she's root). This
- * implements append-only directories.
- */
- if ((dp->i_mode & ISVTX) &&
- VOP_ACCESS(vdp, VADMIN, cred, cnp->cn_thread) &&
- VOP_ACCESS(tdp, VADMIN, cred, cnp->cn_thread)) {
- vput(tdp);
- return (EPERM);
- }
+
*vpp = tdp;
return (0);
}
More information about the p4-projects
mailing list