Skip to content

Commit

Permalink
Fix namespace handling in zpl_permission (#244)
Browse files Browse the repository at this point in the history
This commit fixes user / idmap namespaces in zpl_permission.
ZFS updates to address kernel changes were subtly broken and
passing the wrong namespace to generic_permission().

Since zpl_permission was initially written, zfs_zaccess() has
become idmap-aware. This commit switches from using zfs_access to
zfs_zaccess() and improves zfs_zaccess_aces_check() so that
uids / gids in ACL entries are converted via idmap configuration
prior to checking access.

Signed-off-by: Andrew Walker <[email protected]>
  • Loading branch information
anodos325 authored Aug 12, 2024
1 parent 072c9ab commit 1bc02e2
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
7 changes: 6 additions & 1 deletion module/os/linux/zfs/zfs_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2442,8 +2442,11 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
break;
case OWNING_GROUP:
who = gowner;
zfs_fallthrough;
checkit = zfs_groupmember(zfsvfs, who, cr);
break;
case ACE_IDENTIFIER_GROUP:
who = zfs_gid_to_vfsgid(mnt_ns, zfs_i_user_ns(ZTOI(zp)),
who);
checkit = zfs_groupmember(zfsvfs, who, cr);
break;
case ACE_EVERYONE:
Expand All @@ -2454,6 +2457,8 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
default:
if (entry_type == 0) {
uid_t newid;
who = zfs_uid_to_vfsuid(mnt_ns,
zfs_i_user_ns(ZTOI(zp)), who);

newid = zfs_fuid_map_id(zfsvfs, who, cr,
ZFS_ACE_USER);
Expand Down
34 changes: 27 additions & 7 deletions module/os/linux/zfs/zpl_xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1507,6 +1507,7 @@ zpl_permission(struct inode *ip, int mask)
{
int to_check = 0, i, ret;
cred_t *cr = NULL;
zfsvfs_t *zfsvfs = NULL;

/*
* If NFSv4 ACLs are not being used, go back to
Expand All @@ -1516,9 +1517,10 @@ zpl_permission(struct inode *ip, int mask)
*/
if ((ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_NFSV4) ||
((ITOZ(ip)->z_pflags & ZFS_ACL_TRIVIAL && GENERIC_MASK(mask)))) {
#if (defined(HAVE_IOPS_PERMISSION_USERNS) || \
defined(HAVE_IOPS_PERMISSION_IDMAP))
return (generic_permission(zfs_init_idmap, ip, mask));
#if defined(HAVE_IOPS_PERMISSION_USERNS)
return (generic_permission(userns, ip, mask));
#elif defined(HAVE_IOPS_PERMISSION_IDMAP)
return (generic_permission(idmap, ip, mask));
#else
return (generic_permission(ip, mask));
#endif
Expand All @@ -1535,9 +1537,10 @@ zpl_permission(struct inode *ip, int mask)
* NFSv4 ACE. Pass back to default kernel permissions check.
*/
if (to_check == 0) {
#if (defined(HAVE_IOPS_PERMISSION_USERNS) || \
defined(HAVE_IOPS_PERMISSION_IDMAP))
return (generic_permission(zfs_init_idmap, ip, mask));
#if defined(HAVE_IOPS_PERMISSION_USERNS)
return (generic_permission(userns, ip, mask));
#elif defined(HAVE_IOPS_PERMISSION_IDMAP)
return (generic_permission(idmap, ip, mask));
#else
return (generic_permission(ip, mask));
#endif
Expand Down Expand Up @@ -1614,7 +1617,24 @@ zpl_permission(struct inode *ip, int mask)
return (-ECHILD);
}

ret = -zfs_access(ITOZ(ip), to_check, V_ACE_MASK, cr);
zfsvfs = ZTOZSB(ITOZ(ip));

if ((ret = -zfs_enter_verify_zp(zfsvfs, ITOZ(ip), FTAG)) != 0)
return (ret);

#if defined(HAVE_IOPS_PERMISSION_USERNS)
ret = -zfs_zaccess(ITOZ(ip), to_check, V_ACE_MASK, B_FALSE, cr,
userns);
#elif defined(HAVE_IOPS_PERMISSION_IDMAP)
ret = -zfs_zaccess(ITOZ(ip), to_check, V_ACE_MASK, B_FALSE, cr,
idmap);
#else
ret = -zfs_zaccess(ITOZ(ip), to_check, V_ACE_MASK, B_FALSE, cr,
zfs_init_idmap);
#endif

zfs_exit(zfsvfs, FTAG);

crfree(cr);
return (ret);
}
Expand Down

0 comments on commit 1bc02e2

Please sign in to comment.