diff options
| author | Mateusz Guzik <mjg@FreeBSD.org> | 2020-01-30 02:16:17 +0000 | 
|---|---|---|
| committer | Mateusz Guzik <mjg@FreeBSD.org> | 2020-01-30 02:16:17 +0000 | 
| commit | 42a9f8f21d636f38a2d71b7a84a686eb436886f9 (patch) | |
| tree | 6bbe49879b3d4b2b24de97599dcfad56d1a5b7da | |
| parent | e196f7825e61ad86d86dd9761ba5b230f7088007 (diff) | |
Notes
3 files changed, 43 insertions, 0 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h index 48f55a03f19fe..b34360a3c821d 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h @@ -214,7 +214,10 @@ void zfs_oldace_byteswap(ace_t *, int);  void zfs_ace_byteswap(void *, size_t, boolean_t);  extern boolean_t zfs_has_access(struct znode *zp, cred_t *cr);  extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *); +#ifdef illumos  int zfs_fastaccesschk_execute(struct znode *, cred_t *); +#endif +int zfs_freebsd_fastaccesschk_execute(struct vnode *, cred_t *);  extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *);  extern int zfs_zaccess_unix(struct znode *, mode_t, cred_t *);  extern int zfs_acl_access(struct znode *, int, cred_t *); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c index 6332559edd746..6527b5878e60c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c @@ -2299,6 +2299,40 @@ zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs,  	    check_privs, B_FALSE, cr));  } +/* + * Check if VEXEC is allowed. + * + * This routine is based on zfs_fastaccesschk_execute which has slowpath + * calling zfs_zaccess. This would be incorrect on FreeBSD (see + * zfs_freebsd_access for the difference). Thus this variant let's the + * caller handle the slowpath (if necessary). + * + * We only check for ZFS_NO_EXECS_DENIED and fail early. This routine can + * be extended to cover more cases, but the flag covers the majority. + */ +int +zfs_freebsd_fastaccesschk_execute(struct vnode *vp, cred_t *cr) +{ +	boolean_t is_attr; +	znode_t *zdp = VTOZ(vp); + +	ASSERT_VOP_LOCKED(vp, __func__); + +	if (zdp->z_pflags & ZFS_AV_QUARANTINED) +		return (1); + +	is_attr = ((zdp->z_pflags & ZFS_XATTR) && +	    (ZTOV(zdp)->v_type == VDIR)); +	if (is_attr) +		return (1); + +	if (zdp->z_pflags & ZFS_NO_EXECS_DENIED) +		return (0); + +	return (1); +} + +#ifdef illumos  int  zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)  { @@ -2365,6 +2399,7 @@ slow:  	ZFS_EXIT(zdp->z_zfsvfs);  	return (error);  } +#endif  /*   * Determine whether Access should be granted/denied. 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 3ddd22507e917..cd39ad56e24e4 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 @@ -4858,6 +4858,11 @@ zfs_freebsd_access(ap)  	accmode_t accmode;  	int error = 0; +	if (ap->a_accmode == VEXEC) { +		if (zfs_freebsd_fastaccesschk_execute(ap->a_vp, ap->a_cred) == 0) +			return (0); +	} +  	/*  	 * ZFS itself only knowns about VREAD, VWRITE, VEXEC and VAPPEND,  	 */  | 
