diff options
author | trasz <trasz@FreeBSD.org> | 2009-05-30 13:59:05 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2009-05-30 13:59:05 +0000 |
commit | 0c63bcbfa4fb9f208ea176334478d17cafd66eac (patch) | |
tree | 9fe18e8e703d17defbd688d53ac96d8a33a828de /sys/kern | |
parent | 3b6c3312d5f59aa27a7bb6530afb6f2546934c5f (diff) | |
download | FreeBSD-src-0c63bcbfa4fb9f208ea176334478d17cafd66eac.zip FreeBSD-src-0c63bcbfa4fb9f208ea176334478d17cafd66eac.tar.gz |
Add VOP_ACCESSX, which can be used to query for newly added V*
permissions, such as VWRITE_ACL. For a filsystems that don't
implement it, there is a default implementation, which works
as a wrapper around VOP_ACCESS.
Reviewed by: rwatson@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_default.c | 17 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 47 | ||||
-rw-r--r-- | sys/kern/vnode_if.src | 10 |
3 files changed, 74 insertions, 0 deletions
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index bbaca4b..5e5c2da 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -87,6 +87,7 @@ struct vop_vector default_vnodeops = { .vop_default = NULL, .vop_bypass = VOP_EOPNOTSUPP, + .vop_accessx = vop_stdaccessx, .vop_advlock = vop_stdadvlock, .vop_advlockasync = vop_stdadvlockasync, .vop_bmap = vop_stdbmap, @@ -322,6 +323,22 @@ out: return (found); } +int +vop_stdaccessx(struct vop_accessx_args *ap) +{ + int error; + accmode_t accmode = ap->a_accmode; + + error = vfs_unixify_accmode(&accmode); + if (error != 0) + return (error); + + if (accmode == 0) + return (0); + + return (VOP_ACCESS(ap->a_vp, accmode, ap->a_cred, ap->a_td)); +} + /* * Advisory record locking support */ diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 05d9de5..cee1f2a 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -4253,3 +4253,50 @@ vfs_mark_atime(struct vnode *vp, struct ucred *cred) if ((vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0) (void)VOP_MARKATIME(vp); } + +/* + * The purpose of this routine is to remove granularity from accmode_t, + * reducing it into standard unix access bits - VEXEC, VREAD, VWRITE, + * VADMIN and VAPPEND. + * + * If it returns 0, the caller is supposed to continue with the usual + * access checks using 'accmode' as modified by this routine. If it + * returns nonzero value, the caller is supposed to return that value + * as errno. + * + * Note that after this routine runs, accmode may be zero. + */ +int +vfs_unixify_accmode(accmode_t *accmode) +{ + /* + * There is no way to specify explicit "deny" rule using + * file mode or POSIX.1e ACLs. + */ + if (*accmode & VEXPLICIT_DENY) { + *accmode = 0; + return (0); + } + + /* + * None of these can be translated into usual access bits. + * Also, the common case for NFSv4 ACLs is to not contain + * either of these bits. Caller should check for VWRITE + * on the containing directory instead. + */ + if (*accmode & (VDELETE_CHILD | VDELETE)) + return (EPERM); + + if (*accmode & VADMIN_PERMS) { + *accmode &= ~VADMIN_PERMS; + *accmode |= VADMIN; + } + + /* + * There is no way to deny VREAD_ATTRIBUTES, VREAD_ACL + * or VSYNCHRONIZE using file mode or POSIX.1e ACL. + */ + *accmode &= ~(VSTAT_PERMS | VSYNCHRONIZE); + + return (0); +} diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index b7d9cb1..81c0dff 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -153,6 +153,16 @@ vop_access { }; +%% accessx vp L L L + +vop_accessx { + IN struct vnode *vp; + IN accmode_t accmode; + IN struct ucred *cred; + IN struct thread *td; +}; + + %% getattr vp L L L vop_getattr { |