Support idmapped mount in user namespace

Linux 5.17 commit torvalds/linux@5dfbfe71e enables "the idmapping 
infrastructure to support idmapped mounts of filesystems mounted 
with an idmapping". Update the OpenZFS accordingly to improve the 
idmapped mount support. 

This pull request contains the following changes:

- xattr setter functions are fixed to take mnt_ns argument. Without
  this, cp -p would fail for an idmapped mount in a user namespace.
- idmap_util is enhanced/fixed for its use in a user ns context.
- One test case added to test idmapped mount in a user ns.

Reviewed-by: Christian Brauner <christian@brauner.io>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Youzhong Yang <yyang@mathworks.com>
Closes #14097
This commit is contained in:
youzhongyang
2022-11-08 13:28:56 -05:00
committed by GitHub
parent 109731cd73
commit f224eddf92
21 changed files with 424 additions and 96 deletions
+27 -7
View File
@@ -499,7 +499,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value,
vap->va_gid = crgetgid(cr);
error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp,
cr, 0, NULL, NULL);
cr, 0, NULL, kcred->user_ns);
if (error)
goto out;
}
@@ -738,9 +738,11 @@ __zpl_xattr_user_get(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get);
static int
__zpl_xattr_user_set(struct inode *ip, const char *name,
__zpl_xattr_user_set(struct user_namespace *user_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
(void) user_ns;
int error = 0;
/* xattr_resolve_name will do this for us if this is defined */
#ifndef HAVE_XATTR_HANDLER_NAME
@@ -846,9 +848,11 @@ __zpl_xattr_trusted_get(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get);
static int
__zpl_xattr_trusted_set(struct inode *ip, const char *name,
__zpl_xattr_trusted_set(struct user_namespace *user_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
(void) user_ns;
char *xattr_name;
int error;
@@ -914,9 +918,11 @@ __zpl_xattr_security_get(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get);
static int
__zpl_xattr_security_set(struct inode *ip, const char *name,
__zpl_xattr_security_set(struct user_namespace *user_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
(void) user_ns;
char *xattr_name;
int error;
/* xattr_resolve_name will do this for us if this is defined */
@@ -940,7 +946,7 @@ zpl_xattr_security_init_impl(struct inode *ip, const struct xattr *xattrs,
int error = 0;
for (xattr = xattrs; xattr->name != NULL; xattr++) {
error = __zpl_xattr_security_set(ip,
error = __zpl_xattr_security_set(NULL, ip,
xattr->name, xattr->value, xattr->value_len, 0);
if (error < 0)
@@ -1300,7 +1306,8 @@ __zpl_xattr_acl_get_default(struct inode *ip, const char *name,
ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_default);
static int
__zpl_xattr_acl_set_access(struct inode *ip, const char *name,
__zpl_xattr_acl_set_access(struct user_namespace *mnt_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
struct posix_acl *acl;
@@ -1314,8 +1321,14 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name,
if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
return (-EOPNOTSUPP);
#if defined(HAVE_XATTR_SET_USERNS)
if (!zpl_inode_owner_or_capable(mnt_ns, ip))
return (-EPERM);
#else
(void) mnt_ns;
if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
return (-EPERM);
#endif
if (value) {
acl = zpl_acl_from_xattr(value, size);
@@ -1339,7 +1352,8 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name,
ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_access);
static int
__zpl_xattr_acl_set_default(struct inode *ip, const char *name,
__zpl_xattr_acl_set_default(struct user_namespace *mnt_ns,
struct inode *ip, const char *name,
const void *value, size_t size, int flags)
{
struct posix_acl *acl;
@@ -1353,8 +1367,14 @@ __zpl_xattr_acl_set_default(struct inode *ip, const char *name,
if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX)
return (-EOPNOTSUPP);
#if defined(HAVE_XATTR_SET_USERNS)
if (!zpl_inode_owner_or_capable(mnt_ns, ip))
return (-EPERM);
#else
(void) mnt_ns;
if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
return (-EPERM);
#endif
if (value) {
acl = zpl_acl_from_xattr(value, size);