From owner-p4-projects@FreeBSD.ORG Tue Jul 8 12:19:59 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id B6E44106567E; Tue, 8 Jul 2008 12:19:58 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 791BC106564A for ; Tue, 8 Jul 2008 12:19:58 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 6508E8FC0A for ; Tue, 8 Jul 2008 12:19:58 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m68CJwkK035702 for ; Tue, 8 Jul 2008 12:19:58 GMT (envelope-from trasz@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m68CJwCT035698 for perforce@freebsd.org; Tue, 8 Jul 2008 12:19:58 GMT (envelope-from trasz@freebsd.org) Date: Tue, 8 Jul 2008 12:19:58 GMT Message-Id: <200807081219.m68CJwCT035698@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to trasz@freebsd.org using -f From: Edward Tomasz Napierala To: Perforce Change Reviews Cc: Subject: PERFORCE change 144877 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Jul 2008 12:19:59 -0000 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 - * ( & & ) + * 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,