Date: Sat, 30 May 2009 13:59:05 +0000 (UTC) From: Edward Tomasz Napierala <trasz@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r193092 - in head: share/man/man9 sys/fs/nullfs sys/kern sys/sys Message-ID: <200905301359.n4UDx5Zo009796@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: trasz Date: Sat May 30 13:59:05 2009 New Revision: 193092 URL: http://svn.freebsd.org/changeset/base/193092 Log: 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@ Modified: head/share/man/man9/Makefile head/share/man/man9/VOP_ACCESS.9 head/sys/fs/nullfs/null_vnops.c head/sys/kern/vfs_default.c head/sys/kern/vfs_subr.c head/sys/kern/vnode_if.src head/sys/sys/vnode.h Modified: head/share/man/man9/Makefile ============================================================================== --- head/share/man/man9/Makefile Sat May 30 12:26:11 2009 (r193091) +++ head/share/man/man9/Makefile Sat May 30 13:59:05 2009 (r193092) @@ -1288,6 +1288,7 @@ MLINKS+=vm_page_io.9 vm_page_io_finish.9 MLINKS+=vm_page_wakeup.9 vm_page_busy.9 \ vm_page_wakeup.9 vm_page_flash.9 MLINKS+=vm_page_wire.9 vm_page_unwire.9 +MLINKS+=VOP_ACCESS.9 VOP_ACCESSX.9 MLINKS+=VOP_ATTRIB.9 VOP_GETATTR.9 \ VOP_ATTRIB.9 VOP_SETATTR.9 MLINKS+=VOP_CREATE.9 VOP_MKDIR.9 \ Modified: head/share/man/man9/VOP_ACCESS.9 ============================================================================== --- head/share/man/man9/VOP_ACCESS.9 Sat May 30 12:26:11 2009 (r193091) +++ head/share/man/man9/VOP_ACCESS.9 Sat May 30 13:59:05 2009 (r193092) @@ -29,17 +29,20 @@ .\" .\" $FreeBSD$ .\" -.Dd July 24, 1996 +.Dd May 30, 2009 .Os .Dt VOP_ACCESS 9 .Sh NAME -.Nm VOP_ACCESS +.Nm VOP_ACCESS , +.Nm VOP_ACCESSX .Nd "check access permissions of a file or Unix domain socket" .Sh SYNOPSIS .In sys/param.h .In sys/vnode.h .Ft int .Fn VOP_ACCESS "struct vnode *vp" "accmode_t accmode" "struct ucred *cred" "struct thread *td" +.Ft int +.Fn VOP_ACCESSX "struct vnode *vp" "accmode_t accmode" "struct ucred *cred" "struct thread *td" .Sh DESCRIPTION This entry point checks the access permissions of the file against the given credentials. @@ -63,6 +66,20 @@ is a mask which can contain flags descri .Dv VWRITE or .Dv VEXEC . +For +.Fn VOP_ACCESS , +the only flags that may be set in +.Fa accmode +are +.Dv VEXEC , +.Dv VWRITE , +.Dv VREAD , +.Dv VADMIN +and +.Dv VAPPEND . +To check for other bits, one has to use +.Fn VOP_ACCESSX +instead. .Sh LOCKS The vnode will be locked on entry and should remain locked on return. .Sh RETURN VALUES Modified: head/sys/fs/nullfs/null_vnops.c ============================================================================== --- head/sys/fs/nullfs/null_vnops.c Sat May 30 12:26:11 2009 (r193091) +++ head/sys/fs/nullfs/null_vnops.c Sat May 30 13:59:05 2009 (r193092) @@ -472,6 +472,32 @@ null_access(struct vop_access_args *ap) return (null_bypass((struct vop_generic_args *)ap)); } +static int +null_accessx(struct vop_accessx_args *ap) +{ + struct vnode *vp = ap->a_vp; + accmode_t accmode = ap->a_accmode; + + /* + * Disallow write attempts on read-only layers; + * unless the file is a socket, fifo, or a block or + * character device resident on the filesystem. + */ + if (accmode & VWRITE) { + switch (vp->v_type) { + case VDIR: + case VLNK: + case VREG: + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + break; + default: + break; + } + } + return (null_bypass((struct vop_generic_args *)ap)); +} + /* * We handle this to eliminate null FS to lower FS * file moving. Don't know why we don't allow this, @@ -720,6 +746,7 @@ null_vptofh(struct vop_vptofh_args *ap) struct vop_vector null_vnodeops = { .vop_bypass = null_bypass, .vop_access = null_access, + .vop_accessx = null_accessx, .vop_bmap = VOP_EOPNOTSUPP, .vop_getattr = null_getattr, .vop_getwritemount = null_getwritemount, Modified: head/sys/kern/vfs_default.c ============================================================================== --- head/sys/kern/vfs_default.c Sat May 30 12:26:11 2009 (r193091) +++ head/sys/kern/vfs_default.c Sat May 30 13:59:05 2009 (r193092) @@ -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 */ Modified: head/sys/kern/vfs_subr.c ============================================================================== --- head/sys/kern/vfs_subr.c Sat May 30 12:26:11 2009 (r193091) +++ head/sys/kern/vfs_subr.c Sat May 30 13:59:05 2009 (r193092) @@ -4253,3 +4253,50 @@ vfs_mark_atime(struct vnode *vp, struct 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); +} Modified: head/sys/kern/vnode_if.src ============================================================================== --- head/sys/kern/vnode_if.src Sat May 30 12:26:11 2009 (r193091) +++ head/sys/kern/vnode_if.src Sat May 30 13:59:05 2009 (r193092) @@ -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 { Modified: head/sys/sys/vnode.h ============================================================================== --- head/sys/sys/vnode.h Sat May 30 12:26:11 2009 (r193091) +++ head/sys/sys/vnode.h Sat May 30 13:59:05 2009 (r193092) @@ -676,6 +676,7 @@ int vop_stdlock(struct vop_lock1_args *) int vop_stdputpages(struct vop_putpages_args *); int vop_stdunlock(struct vop_unlock_args *); int vop_nopoll(struct vop_poll_args *); +int vop_stdaccessx(struct vop_accessx_args *ap); int vop_stdadvlock(struct vop_advlock_args *ap); int vop_stdadvlockasync(struct vop_advlockasync_args *ap); int vop_stdpathconf(struct vop_pathconf_args *); @@ -766,6 +767,8 @@ void vfs_mark_atime(struct vnode *vp, st struct dirent; int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off); +int vfs_unixify_accmode(accmode_t *accmode); + #endif /* _KERNEL */ #endif /* !_SYS_VNODE_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905301359.n4UDx5Zo009796>