diff options
| author | Kyle Evans <kevans@FreeBSD.org> | 2020-02-02 16:34:57 +0000 |
|---|---|---|
| committer | Kyle Evans <kevans@FreeBSD.org> | 2020-02-02 16:34:57 +0000 |
| commit | 6a5abb1ee5351d36de3b8589f8bf23fd2dfbb6da (patch) | |
| tree | db300f6040643046bb920b04cfb37a8576cec10d /sys | |
| parent | c887ac83245115c57c0b8df29ce5048122a88418 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c | 12 | ||||
| -rw-r--r-- | sys/fs/devfs/devfs_vnops.c | 4 | ||||
| -rw-r--r-- | sys/fs/fuse/fuse_vnops.c | 4 | ||||
| -rw-r--r-- | sys/fs/nfsclient/nfs_clvnops.c | 3 | ||||
| -rw-r--r-- | sys/fs/smbfs/smbfs_vnops.c | 3 | ||||
| -rw-r--r-- | sys/fs/tmpfs/tmpfs_vnops.c | 2 | ||||
| -rw-r--r-- | sys/kern/vfs_cache.c | 6 | ||||
| -rw-r--r-- | sys/kern/vfs_lookup.c | 19 | ||||
| -rw-r--r-- | sys/kern/vfs_subr.c | 12 | ||||
| -rw-r--r-- | sys/sys/fcntl.h | 2 | ||||
| -rw-r--r-- | sys/sys/namei.h | 3 | ||||
| -rw-r--r-- | sys/sys/vnode.h | 2 |
12 files changed, 54 insertions, 18 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 1c2856a224b34..26cce46bc92ea 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -1543,10 +1543,14 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp, * Check accessibility of directory. */ if (!cached) { - error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr); - if (error != 0) { - ZFS_EXIT(zfsvfs); - return (error); + if ((cnp->cn_flags & NOEXECCHECK) != 0) { + cnp->cn_flags &= ~NOEXECCHECK; + } else { + error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr); + if (error != 0) { + ZFS_EXIT(zfsvfs); + return (error); + } } } diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 8f60bfc414c32..05b30a0630239 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -946,8 +946,8 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock) if ((flags & ISDOTDOT) && (dvp->v_vflag & VV_ROOT)) return (EIO); - error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td); - if (error) + error = vn_dir_check_exec(dvp, cnp); + if (error != 0) return (error); if (cnp->cn_namelen == 1 && *pname == '.') { diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index f1b0fcbe7bdf3..05431a7706572 100644 --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -1006,7 +1006,9 @@ fuse_vnop_lookup(struct vop_lookup_args *ap) if (islastcn && vfs_isrdonly(mp) && (nameiop != LOOKUP)) return EROFS; - if ((err = fuse_internal_access(dvp, VEXEC, td, cred))) + if ((cnp->cn_flags & NOEXECCHECK) != 0) + cnp->cn_flags &= ~NOEXECCHECK; + else if ((err = fuse_internal_access(dvp, VEXEC, td, cred))) return err; if (flags & ISDOTDOT) { diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 63b1ab76975b9..9c929e9af3b5a 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -1195,7 +1195,8 @@ nfs_lookup(struct vop_lookup_args *ap) } NFSUNLOCKNODE(np); - if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) + error = vn_dir_check_exec(dvp, cnp); + if (error != 0) return (error); error = cache_lookup(dvp, vpp, cnp, &nctime, &ncticks); if (error > 0 && error != ENOENT) diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c index 3a0c207f685c0..026fab8d000c9 100644 --- a/sys/fs/smbfs/smbfs_vnops.c +++ b/sys/fs/smbfs/smbfs_vnops.c @@ -1199,7 +1199,8 @@ smbfs_lookup(ap) islastcn = flags & ISLASTCN; if (islastcn && (mp->mnt_flag & MNT_RDONLY) && (nameiop != LOOKUP)) return EROFS; - if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) + error = vn_dir_check_exec(dvp, cnp); + if (error != 0) return error; smp = VFSTOSMBFS(mp); dnp = VTOSMB(dvp); diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 570c33c33491a..088258918d14e 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -90,7 +90,7 @@ tmpfs_lookup1(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) *vpp = NULLVP; /* Check accessibility of requested node as a first step. */ - error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_thread); + error = vn_dir_check_exec(dvp, cnp); if (error != 0) goto out; diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index fecf749578e3b..f0026e1be18e9 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -2141,9 +2141,7 @@ vfs_cache_lookup(struct vop_lookup_args *ap) int error; struct vnode **vpp = ap->a_vpp; struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; int flags = cnp->cn_flags; - struct thread *td = cnp->cn_thread; *vpp = NULL; dvp = ap->a_dvp; @@ -2155,8 +2153,8 @@ vfs_cache_lookup(struct vop_lookup_args *ap) (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return (EROFS); - error = VOP_ACCESS(dvp, VEXEC, cred, td); - if (error) + error = vn_dir_check_exec(dvp, cnp); + if (error != 0) return (error); error = cache_lookup(dvp, vpp, cnp, NULL, NULL); diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 265fd724d0f96..9e55c1426455d 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -308,6 +308,7 @@ namei(struct nameidata *ndp) struct vnode *dp; /* the directory we are searching */ struct iovec aiov; /* uio for reading symbolic links */ struct componentname *cnp; + struct file *dfp; struct thread *td; struct proc *p; cap_rights_t rights; @@ -445,10 +446,22 @@ namei(struct nameidata *ndp) AUDIT_ARG_ATFD1(ndp->ni_dirfd); if (cnp->cn_flags & AUDITVNODE2) AUDIT_ARG_ATFD2(ndp->ni_dirfd); - error = fgetvp_rights(td, ndp->ni_dirfd, - &rights, &ndp->ni_filecaps, &dp); - if (error == EINVAL) + /* + * Effectively inlined fgetvp_rights, because we need to + * inspect the file as well as grabbing the vnode. + */ + error = fget_cap_locked(fdp, ndp->ni_dirfd, &rights, + &dfp, &ndp->ni_filecaps); + if (error != 0 || dfp->f_ops == &badfileops || + dfp->f_vnode == NULL) { error = ENOTDIR; + } else { + dp = dfp->f_vnode; + vrefact(dp); + + if ((dfp->f_flag & FSEARCH) != 0) + cnp->cn_flags |= NOEXECCHECK; + } #ifdef CAPABILITIES /* * If file descriptor doesn't have all rights, diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 6f9d37d03ccd6..f9f1f0a541c63 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -6377,3 +6377,15 @@ __mnt_vnode_markerfree_lazy(struct vnode **mvp, struct mount *mp) mtx_unlock(&mp->mnt_listmtx); mnt_vnode_markerfree_lazy(mvp, mp); } + +int +vn_dir_check_exec(struct vnode *vp, struct componentname *cnp) +{ + + if ((cnp->cn_flags & NOEXECCHECK) != 0) { + cnp->cn_flags &= ~NOEXECCHECK; + return (0); + } + + return (VOP_ACCESS(vp, VEXEC, cnp->cn_cred, cnp->cn_thread)); +} diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index 55ba4220afefe..0febbcec5cd5b 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -119,9 +119,11 @@ typedef __pid_t pid_t; #if __POSIX_VISIBLE >= 200809 #define O_DIRECTORY 0x00020000 /* Fail if not directory */ #define O_EXEC 0x00040000 /* Open for execute only */ +#define O_SEARCH O_EXEC #endif #ifdef _KERNEL #define FEXEC O_EXEC +#define FSEARCH O_SEARCH #endif #if __POSIX_VISIBLE >= 200809 diff --git a/sys/sys/namei.h b/sys/sys/namei.h index bd5198bd936f5..602d7eff28b23 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -161,7 +161,8 @@ struct nameidata { #define AUDITVNODE2 0x08000000 /* audit the looked up vnode information */ #define TRAILINGSLASH 0x10000000 /* path ended in a slash */ #define NOCAPCHECK 0x20000000 /* do not perform capability checks */ -#define PARAMASK 0x3ffffe00 /* mask of parameter descriptors */ +#define NOEXECCHECK 0x40000000 /* do not perform exec check on dir */ +#define PARAMASK 0x7ffffe00 /* mask of parameter descriptors */ /* * Namei results flags diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 809427d00d15d..19c4930263db0 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -953,6 +953,8 @@ int vn_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred, void vn_fsid(struct vnode *vp, struct vattr *va); +int vn_dir_check_exec(struct vnode *vp, struct componentname *cnp); + #define VOP_UNLOCK_FLAGS(vp, flags) ({ \ struct vnode *_vp = (vp); \ int _flags = (flags); \ |
