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@
This commit is contained in:
parent
a16ccdcead
commit
c97fcdba57
@ -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 \
|
||||
|
@ -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 described in <sys/vnode.h>, e.g.
|
||||
.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
|
||||
|
@ -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,
|
||||
|
@ -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 @@ dirent_exists(struct vnode *vp, const char *dirname, struct thread *td)
|
||||
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
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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, struct ucred *cred);
|
||||
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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user