diff --git a/module/os/linux/zfs/policy.c b/module/os/linux/zfs/policy.c index f8a8086046..ebec1e93a4 100644 --- a/module/os/linux/zfs/policy.c +++ b/module/os/linux/zfs/policy.c @@ -114,17 +114,22 @@ secpolicy_vnode_access2(const cred_t *cr, struct inode *ip, uid_t owner, mode_t curmode, mode_t wantmode) { mode_t remainder = ~curmode & wantmode; + uid_t uid = crgetuid(cr); if ((ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_NFSV4) || (remainder == 0)) { return (0); } - /* - * short-circuit if root - */ - if (capable(CAP_SYS_ADMIN)) { + if ((uid == owner) || (uid == 0)) return (0); - } + + if (zpl_inode_owner_or_capable(kcred->user_ns, ip)) + return (0); + +#if defined(CONFIG_USER_NS) + if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner))) + return (EPERM); +#endif /* * There are some situations in which capabilities @@ -132,20 +137,22 @@ secpolicy_vnode_access2(const cred_t *cr, struct inode *ip, uid_t owner, */ if (S_ISDIR(ip->i_mode)) { if (!(wantmode & S_IWUSR) && - capable(CAP_DAC_READ_SEARCH)) { + (priv_policy_user(cr, CAP_DAC_READ_SEARCH, EPERM) == 0)) { return (0); } - if (capable(CAP_DAC_OVERRIDE)) { + if (priv_policy_user(cr, CAP_DAC_OVERRIDE, EPERM) == 0) { return (0); } return (EACCES); } - if ((wantmode == S_IRUSR) && capable(CAP_DAC_READ_SEARCH)) { + if ((wantmode == S_IRUSR) && + (priv_policy_user(cr, CAP_DAC_READ_SEARCH, EPERM) == 0)) { return (0); } - if (!(remainder & S_IXUSR) && capable(CAP_DAC_OVERRIDE)) { + if (!(remainder & S_IXUSR) && + (priv_policy_user(cr, CAP_DAC_OVERRIDE, EPERM) == 0)) { return (0); } diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c index 4005258728..332dc63970 100644 --- a/module/os/linux/zfs/zpl_xattr.c +++ b/module/os/linux/zfs/zpl_xattr.c @@ -107,7 +107,8 @@ static const struct { #endif }; -#define GENERIC_MASK(mask) ((mask & ~(MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) +#define POSIX_MASKS (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_OPEN) +#define GENERIC_MASK(mask) ((mask & ~POSIX_MASKS) == 0) enum xattr_permission { XAPERM_DENY,