From 85fab2b2001b57d8c9709398223212e27e8a2238 Mon Sep 17 00:00:00 2001 From: "J. R. Okajima" <hooanon05g@gmail.com> Date: Thu, 4 Mar 2021 11:33:45 +0900 Subject: [PATCH] aufs: v5.12-rc1 idmapper userns 1/2, new parameter In mainline, by the commit 549c7297717c3 2021-01-24 fs: make helpers idmap mount aware and its series, a new parameter 'user_ns' was added to some inode operations. Aufs simply follows it, but it is still testing. Signed-off-by: J. R. Okajima <hooanon05g@gmail.com> --- fs/aufs/branch.h | 11 +++++++++ fs/aufs/cpup.c | 34 ++++++++++++++++++--------- fs/aufs/dentry.c | 18 +++++++++----- fs/aufs/dentry.h | 3 ++- fs/aufs/dir.c | 4 +++- fs/aufs/i_op.c | 39 ++++++++++++++++++++----------- fs/aufs/i_op_add.c | 21 ++++++++++------- fs/aufs/i_op_del.c | 6 +++-- fs/aufs/i_op_ren.c | 3 ++- fs/aufs/inode.c | 10 ++++---- fs/aufs/inode.h | 37 +++++++++++++++++------------ fs/aufs/posix_acl.c | 3 ++- fs/aufs/super.c | 5 +++- fs/aufs/vfsub.c | 57 ++++++++++++++++++++++++++++++++++----------- fs/aufs/vfsub.h | 18 ++++++++------ fs/aufs/whout.c | 24 ++++++++++++------- fs/aufs/whout.h | 5 ++-- fs/aufs/xattr.c | 34 ++++++++++++++++++--------- fs/aufs/xino.c | 2 +- 19 files changed, 227 insertions(+), 107 deletions(-) diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h index 5632781b7bcc4e..ef7e0fb5a9d776 100644 --- a/fs/aufs/branch.h +++ b/fs/aufs/branch.h @@ -133,6 +133,11 @@ static inline struct dentry *au_br_dentry(struct au_branch *br) return br->br_path.dentry; } +static inline struct user_namespace *au_br_userns(struct au_branch *br) +{ + return mnt_user_ns(br->br_path.mnt); +} + static inline struct super_block *au_br_sb(struct au_branch *br) { return au_br_mnt(br)->mnt_sb; @@ -291,6 +296,12 @@ struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex) return au_br_mnt(au_sbr(sb, bindex)); } +static inline +struct user_namespace *au_sbr_userns(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_br_userns(au_sbr(sb, bindex)); +} + static inline struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex) { diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c index d413ad06ca89e3..5f86875573da10 100644 --- a/fs/aufs/cpup.c +++ b/fs/aufs/cpup.c @@ -151,7 +151,7 @@ struct au_cpup_reg_attr { }; static noinline_for_stack -int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, +int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct path *h_src, struct au_cpup_reg_attr *h_src_attr) { int err, sbits, icex; @@ -163,11 +163,11 @@ int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, struct kstat *h_st; struct au_branch *br; - h_path.dentry = au_h_dptr(dst, bindex); - h_idst = d_inode(h_path.dentry); br = au_sbr(dst->d_sb, bindex); h_path.mnt = au_br_mnt(br); - h_isrc = d_inode(h_src); + h_path.dentry = au_h_dptr(dst, bindex); + h_idst = d_inode(h_path.dentry); + h_isrc = d_inode(h_src->dentry); ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID | ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -211,7 +211,7 @@ int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, if (!err) { mnt_flags = au_mntflags(dst->d_sb); verbose = !!au_opt_test(mnt_flags, VERBOSE); - err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose); + err = au_cpup_xattr(&h_path, h_src, icex, verbose); } return err; @@ -581,16 +581,18 @@ static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode) int err; struct dentry *h_dentry; struct inode *h_inode; + struct user_namespace *h_userns; + h_userns = mnt_user_ns(h_path->mnt); h_dentry = h_path->dentry; h_inode = d_inode(h_dentry); /* forget_all_cached_acls(h_inode)); */ - err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); + err = vfsub_removexattr(h_userns, h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); AuTraceErr(err); if (err == -EOPNOTSUPP) err = 0; if (!err) - err = vfsub_acl_chmod(h_inode, mode); + err = vfsub_acl_chmod(h_userns, h_inode, mode); AuTraceErr(err); return err; @@ -601,8 +603,11 @@ static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent, { int err; struct inode *dir, *inode; + struct user_namespace *h_userns; - err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT); + h_userns = mnt_user_ns(h_path->mnt); + err = vfsub_removexattr(h_userns, h_path->dentry, + XATTR_NAME_POSIX_ACL_DEFAULT); AuTraceErr(err); if (err == -EOPNOTSUPP) err = 0; @@ -783,6 +788,7 @@ static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode; struct super_block *sb; struct au_branch *br; + struct path h_src_path; /* to reduce stack size */ struct { struct au_dtime dt; @@ -874,7 +880,9 @@ static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) /* todo: necessary? */ /* au_pin_hdir_unlock(cpg->pin); */ - err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr); + h_src_path.dentry = h_src; + h_src_path.mnt = au_sbr_mnt(sb, cpg->bsrc); + err = cpup_iattr(cpg->dentry, cpg->bdst, &h_src_path, &a->h_src_attr); if (unlikely(err)) { /* todo: necessary? */ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */ @@ -1076,6 +1084,7 @@ static int au_do_sio_cpup_simple(struct au_cp_generic *cpg) struct dentry *dentry, *parent; struct file *h_file; struct inode *h_dir; + struct user_namespace *h_userns; dentry = cpg->dentry; h_file = NULL; @@ -1089,7 +1098,8 @@ static int au_do_sio_cpup_simple(struct au_cp_generic *cpg) parent = dget_parent(dentry); h_dir = au_h_iptr(d_inode(parent), cpg->bdst); - if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE) + h_userns = au_sbr_userns(dentry->d_sb, cpg->bdst); + if (!au_test_h_perm_sio(h_userns, h_dir, MAY_EXEC | MAY_WRITE) && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) err = au_cpup_simple(cpg); else { @@ -1259,6 +1269,7 @@ int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file) struct inode *dir, *h_dir, *h_tmpdir; struct au_wbr *wbr; struct au_pin wh_pin, *pin_orig; + struct user_namespace *h_userns; dentry = cpg->dentry; bdst = cpg->bdst; @@ -1287,7 +1298,8 @@ int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file) cpg->pin = &wh_pin; } - if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE) + h_userns = au_sbr_userns(dentry->d_sb, bdst); + if (!au_test_h_perm_sio(h_userns, h_tmpdir, MAY_EXEC | MAY_WRITE) && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) err = au_cpup_wh(cpg, file); else { diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c index 1a029193315a91..2143add96a2de4 100644 --- a/fs/aufs/dentry.c +++ b/fs/aufs/dentry.c @@ -22,6 +22,7 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry, struct dentry *h_dentry; struct inode *h_inode; struct au_branch *br; + struct user_namespace *h_userns; int wh_found, opq; unsigned char wh_able; const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG); @@ -30,9 +31,11 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry, wh_found = 0; br = au_sbr(dentry->d_sb, bindex); + h_userns = au_br_userns(br); wh_able = !!au_br_whable(br->br_perm); if (wh_able) - wh_found = au_wh_test(h_parent, &args->whname, ignore_perm); + wh_found = au_wh_test(h_userns, h_parent, &args->whname, + ignore_perm); h_dentry = ERR_PTR(wh_found); if (!wh_found) goto real_lookup; @@ -49,7 +52,7 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry, if (!ignore_perm) h_dentry = vfsub_lkup_one(args->name, h_parent); else - h_dentry = au_sio_lkup_one(args->name, h_parent); + h_dentry = au_sio_lkup_one(h_userns, args->name, h_parent); if (IS_ERR(h_dentry)) { if (PTR_ERR(h_dentry) == -ENAMETOOLONG && !allow_neg) @@ -84,7 +87,7 @@ au_do_lookup(struct dentry *h_parent, struct dentry *dentry, goto out; /* success */ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); - opq = au_diropq_test(h_dentry); + opq = au_diropq_test(h_userns, h_dentry); inode_unlock_shared(h_inode); if (opq > 0) au_set_dbdiropq(dentry, bindex); @@ -229,12 +232,13 @@ int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, return err; } -struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent) +struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr *name, + struct dentry *parent) { struct dentry *dentry; int wkq_err; - if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC)) + if (!au_test_h_perm_sio(userns, d_inode(parent), MAY_EXEC)) dentry = vfsub_lkup_one(name, parent); else { struct vfsub_lkup_one_args args = { @@ -259,14 +263,16 @@ int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh) int err; struct dentry *parent, *h_parent, *h_dentry; struct au_branch *br; + struct user_namespace *h_userns; parent = dget_parent(dentry); h_parent = au_h_dptr(parent, bindex); br = au_sbr(dentry->d_sb, bindex); + h_userns = au_br_userns(br); if (wh) h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); else - h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent); + h_dentry = au_sio_lkup_one(h_userns, &dentry->d_name, h_parent); err = PTR_ERR(h_dentry); if (IS_ERR(h_dentry)) goto out; diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h index 086f6ccf4b151a..a9068cbb12540e 100644 --- a/fs/aufs/dentry.h +++ b/fs/aufs/dentry.h @@ -60,7 +60,8 @@ struct au_do_lookup_args { /* dentry.c */ extern const struct dentry_operations aufs_dop, aufs_dop_noreval; struct au_branch; -struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent); +struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr *name, + struct dentry *parent); int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, struct dentry *h_parent, struct au_branch *br); diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c index 44adae19efb1ca..a0206603af125b 100644 --- a/fs/aufs/dir.c +++ b/fs/aufs/dir.c @@ -624,12 +624,14 @@ static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg) int err, wkq_err; struct dentry *h_dentry; struct inode *h_inode; + struct user_namespace *h_userns; + h_userns = au_sbr_userns(dentry->d_sb, arg->bindex); h_dentry = au_h_dptr(dentry, arg->bindex); h_inode = d_inode(h_dentry); /* todo: i_mode changes anytime? */ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); - err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ); + err = au_test_h_perm_sio(h_userns, h_inode, MAY_EXEC | MAY_READ); inode_unlock_shared(h_inode); if (!err) err = do_test_empty(dentry, arg); diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c index 42bc497e263093..edaae92392f2fc 100644 --- a/fs/aufs/i_op.c +++ b/fs/aufs/i_op.c @@ -19,6 +19,7 @@ static int h_permission(struct inode *h_inode, int mask, { int err; const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); + struct user_namespace *h_userns; err = -EPERM; if (write_mask && IS_IMMUTABLE(h_inode)) @@ -38,19 +39,21 @@ static int h_permission(struct inode *h_inode, int mask, * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.' * in this case, generic_permission() returns -EOPNOTSUPP. */ + h_userns = mnt_user_ns(h_path->mnt); if ((write_mask && !au_br_writable(brperm)) || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) && write_mask && !(mask & MAY_READ)) || !h_inode->i_op->permission) { /* AuLabel(generic_permission); */ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */ - err = generic_permission(h_inode, mask); + err = generic_permission(h_userns, h_inode, mask); if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode)) - err = h_inode->i_op->permission(h_inode, mask); + err = h_inode->i_op->permission(h_userns, h_inode, + mask); AuTraceErr(err); } else { /* AuLabel(h_inode->permission); */ - err = h_inode->i_op->permission(h_inode, mask); + err = h_inode->i_op->permission(h_userns, h_inode, mask); AuTraceErr(err); } @@ -63,7 +66,8 @@ static int h_permission(struct inode *h_inode, int mask, return err; } -static int aufs_permission(struct inode *inode, int mask) +static int aufs_permission(struct user_namespace *userns, struct inode *inode, + int mask) { int err; aufs_bindex_t bindex, bbot; @@ -911,18 +915,20 @@ int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, return err; } -static int aufs_setattr(struct dentry *dentry, struct iattr *ia) +static int aufs_setattr(struct user_namespace *userns, struct dentry *dentry, + struct iattr *ia) { int err; struct inode *inode, *delegated; struct super_block *sb; struct file *file; struct au_icpup_args *a; + struct user_namespace *h_userns; inode = d_inode(dentry); IMustLock(inode); - err = setattr_prepare(dentry, ia); + err = setattr_prepare(userns, dentry, ia); if (unlikely(err)) goto out; @@ -1015,8 +1021,10 @@ static int aufs_setattr(struct dentry *dentry, struct iattr *ia) * regardless aufs 'acl' option setting. * why don't all acl-aware fs call this func from their ->setattr()? */ - if (!err && (ia->ia_valid & ATTR_MODE)) - err = vfsub_acl_chmod(a->h_inode, ia->ia_mode); + if (!err && (ia->ia_valid & ATTR_MODE)) { + h_userns = mnt_user_ns(a->h_path.mnt); + err = vfsub_acl_chmod(h_userns, a->h_inode, ia->ia_mode); + } if (!err) au_cpup_attr_changeable(inode); @@ -1078,6 +1086,7 @@ ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, struct super_block *sb; struct au_icpup_args *a; struct inode *h_inode; + struct user_namespace *h_userns; IMustLock(inode); @@ -1096,23 +1105,25 @@ ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, err = au_h_path_to_set_attr(dentry, a, &h_path); if (unlikely(err)) goto out_di; + h_userns = mnt_user_ns(h_path.mnt); inode_unlock(a->h_inode); switch (arg->type) { case AU_XATTR_SET: AuDebugOn(d_is_negative(h_path.dentry)); - err = vfsub_setxattr(h_path.dentry, + err = vfsub_setxattr(h_userns, h_path.dentry, arg->u.set.name, arg->u.set.value, arg->u.set.size, arg->u.set.flags); break; case AU_ACL_SET: err = -EOPNOTSUPP; h_inode = d_inode(h_path.dentry); - if (h_inode->i_op->set_acl) + if (h_inode->i_op->set_acl) { /* this will call posix_acl_update_mode */ - err = h_inode->i_op->set_acl(h_inode, + err = h_inode->i_op->set_acl(h_userns, h_inode, arg->u.acl_set.acl, arg->u.acl_set.type); + } break; } if (!err) @@ -1243,8 +1254,8 @@ int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force, return err; } -static int aufs_getattr(const struct path *path, struct kstat *st, - u32 request, unsigned int query) +static int aufs_getattr(struct user_namespace *userns, const struct path *path, + struct kstat *st, u32 request, unsigned int query) { int err; unsigned char positive; @@ -1281,7 +1292,7 @@ static int aufs_getattr(const struct path *path, struct kstat *st, goto out_di; out_fill: - generic_fillattr(inode, st); + generic_fillattr(userns, inode, st); out_di: di_read_unlock(dentry, AuLock_IR); out_si: diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c index 853c99e200dadc..b8c8e8cd710cf4 100644 --- a/fs/aufs/i_op_add.c +++ b/fs/aufs/i_op_add.c @@ -353,8 +353,8 @@ static int add_simple(struct inode *dir, struct dentry *dentry, return err; } -int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t dev) +int aufs_mknod(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t dev) { struct simple_arg arg = { .type = Mknod, @@ -366,7 +366,8 @@ int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, return add_simple(dir, dentry, &arg); } -int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) +int aufs_symlink(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, const char *symname) { struct simple_arg arg = { .type = Symlink, @@ -375,8 +376,8 @@ int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) return add_simple(dir, dentry, &arg); } -int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, - bool want_excl) +int aufs_create(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, umode_t mode, bool want_excl) { struct simple_arg arg = { .type = Creat, @@ -403,7 +404,8 @@ int au_aopen_or_create(struct inode *dir, struct dentry *dentry, return add_simple(dir, dentry, &arg); } -int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) +int aufs_tmpfile(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, umode_t mode) { int err; aufs_bindex_t bindex; @@ -411,6 +413,7 @@ int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) struct dentry *parent, *h_parent, *h_dentry; struct inode *h_dir, *inode; struct vfsmount *h_mnt; + struct user_namespace *h_userns; struct au_wr_dir_args wr_dir_args = { .force_btgt = -1, .flags = AuWrDir_TMPFILE @@ -457,8 +460,9 @@ int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) if (unlikely(err)) goto out_parent; + h_userns = mnt_user_ns(h_mnt); h_parent = au_h_dptr(parent, bindex); - h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0); + h_dentry = vfs_tmpfile(h_userns, h_parent, mode, /*open_flag*/0); if (IS_ERR(h_dentry)) { err = PTR_ERR(h_dentry); goto out_mnt; @@ -814,7 +818,8 @@ int aufs_link(struct dentry *src_dentry, struct inode *dir, return err; } -int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +int aufs_mkdir(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, umode_t mode) { int err, rerr; aufs_bindex_t bindex; diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c index 05f5d4219b414d..b2940e0b329901 100644 --- a/fs/aufs/i_op_del.c +++ b/fs/aufs/i_op_del.c @@ -81,6 +81,7 @@ int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, umode_t h_mode; struct dentry *h_dentry, *h_latest; struct inode *h_inode; + struct user_namespace *h_userns; h_dentry = au_h_dptr(dentry, bindex); if (d_really_is_positive(dentry)) { @@ -118,12 +119,13 @@ int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, * let's try heavy test. */ err = -EACCES; + h_userns = au_sbr_userns(dentry->d_sb, bindex); if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1) - && au_test_h_perm(d_inode(h_parent), + && au_test_h_perm(h_userns, d_inode(h_parent), MAY_EXEC | MAY_WRITE))) goto out; - h_latest = au_sio_lkup_one(&dentry->d_name, h_parent); + h_latest = au_sio_lkup_one(h_userns, &dentry->d_name, h_parent); err = -EIO; if (IS_ERR(h_latest)) goto out; diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c index 37c52390034a86..54455a762a6175 100644 --- a/fs/aufs/i_op_ren.c +++ b/fs/aufs/i_op_ren.c @@ -940,7 +940,8 @@ static void au_ren_rev_dt(int err, struct au_ren_args *a) /* ---------------------------------------------------------------------- */ -int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, +int aufs_rename(struct user_namespace *userns, + struct inode *_src_dir, struct dentry *_src_dentry, struct inode *_dst_dir, struct dentry *_dst_dentry, unsigned int _flags) { diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c index c071e525f499a7..b1c846a4ce15b1 100644 --- a/fs/aufs/inode.c +++ b/fs/aufs/inode.c @@ -499,18 +499,20 @@ int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, return err; } -int au_test_h_perm(struct inode *h_inode, int mask) +int au_test_h_perm(struct user_namespace *h_userns, struct inode *h_inode, + int mask) { if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) return 0; - return inode_permission(h_inode, mask); + return inode_permission(h_userns, h_inode, mask); } -int au_test_h_perm_sio(struct inode *h_inode, int mask) +int au_test_h_perm_sio(struct user_namespace *h_userns, struct inode *h_inode, + int mask) { if (au_test_nfs(h_inode->i_sb) && (mask & MAY_WRITE) && S_ISDIR(h_inode->i_mode)) mask |= MAY_READ; /* force permission check */ - return au_test_h_perm(h_inode, mask); + return au_test_h_perm(h_userns, h_inode, mask); } diff --git a/fs/aufs/inode.h b/fs/aufs/inode.h index 7f1992a3ef5cf2..2c6d710095139f 100644 --- a/fs/aufs/inode.h +++ b/fs/aufs/inode.h @@ -124,8 +124,10 @@ int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, struct inode *au_new_inode(struct dentry *dentry, int must_new); int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode); -int au_test_h_perm(struct inode *h_inode, int mask); -int au_test_h_perm_sio(struct inode *h_inode, int mask); +int au_test_h_perm(struct user_namespace *h_userns, struct inode *h_inode, + int mask); +int au_test_h_perm_sio(struct user_namespace *h_userns, struct inode *h_inode, + int mask); static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, unsigned int d_type, ino_t *ino) @@ -200,18 +202,21 @@ int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force, /* i_op_add.c */ int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, struct dentry *h_parent, int isdir); -int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t dev); -int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); -int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, - bool want_excl); +int aufs_mknod(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t dev); +int aufs_symlink(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, const char *symname); +int aufs_create(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, umode_t mode, bool want_excl); struct vfsub_aopen_args; int au_aopen_or_create(struct inode *dir, struct dentry *dentry, struct vfsub_aopen_args *args); -int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); +int aufs_tmpfile(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, umode_t mode); int aufs_link(struct dentry *src_dentry, struct inode *dir, struct dentry *dentry); -int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); +int aufs_mkdir(struct user_namespace *userns, struct inode *dir, + struct dentry *dentry, umode_t mode); /* i_op_del.c */ int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); @@ -222,9 +227,10 @@ int aufs_rmdir(struct inode *dir, struct dentry *dentry); /* i_op_ren.c */ int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); -int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, - struct inode *dir, struct dentry *dentry, - unsigned int flags); +int aufs_rename(struct user_namespace *userns, + struct inode *_src_dir, struct dentry *_src_dentry, + struct inode *_dst_dir, struct dentry *_dst_dentry, + unsigned int _flags); /* iinfo.c */ struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); @@ -294,19 +300,20 @@ AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id); #ifdef CONFIG_AUFS_XATTR /* xattr.c */ -int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, +int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags, unsigned int verbose); ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size); void au_xattr_init(struct super_block *sb); #else -AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src, +AuStubInt0(au_cpup_xattr, struct path *h_dst, struct path *h_src, int ignore_flags, unsigned int verbose); AuStubVoid(au_xattr_init, struct super_block *sb); #endif #ifdef CONFIG_FS_POSIX_ACL struct posix_acl *aufs_get_acl(struct inode *inode, int type); -int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type); +int aufs_set_acl(struct user_namespace *userns, struct inode *inode, + struct posix_acl *acl, int type); #endif #if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) diff --git a/fs/aufs/posix_acl.c b/fs/aufs/posix_acl.c index 946c2247e78d11..422315474f8e43 100644 --- a/fs/aufs/posix_acl.c +++ b/fs/aufs/posix_acl.c @@ -50,7 +50,8 @@ struct posix_acl *aufs_get_acl(struct inode *inode, int type) return acl; } -int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type) +int aufs_set_acl(struct user_namespace *userns, struct inode *inode, + struct posix_acl *acl, int type) { int err; ssize_t ssz; diff --git a/fs/aufs/super.c b/fs/aufs/super.c index 589dd01220201b..d252963a87b530 100644 --- a/fs/aufs/super.c +++ b/fs/aufs/super.c @@ -1026,7 +1026,10 @@ static void aufs_kill_sb(struct super_block *sb) struct file_system_type aufs_fs_type = { .name = AUFS_FSTYPE, /* a race between rename and others */ - .fs_flags = FS_RENAME_DOES_D_MOVE, + .fs_flags = FS_RENAME_DOES_D_MOVE + /* untested */ + /*| FS_ALLOW_IDMAP*/ + , .mount = aufs_mount, .kill_sb = aufs_kill_sb, /* no need to __module_get() and module_put(). */ diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c index fa29c543cc28e3..3d8bb5135f423f 100644 --- a/fs/aufs/vfsub.c +++ b/fs/aufs/vfsub.c @@ -231,6 +231,7 @@ int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl) { int err; struct dentry *d; + struct user_namespace *userns; IMustLock(dir); @@ -240,9 +241,10 @@ int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl) path->dentry = d; if (unlikely(err)) goto out; + userns = mnt_user_ns(path->mnt); lockdep_off(); - err = vfs_create(dir, path->dentry, mode, want_excl); + err = vfs_create(userns, dir, path->dentry, mode, want_excl); lockdep_on(); if (!err) { struct path tmp = *path; @@ -264,6 +266,7 @@ int vfsub_symlink(struct inode *dir, struct path *path, const char *symname) { int err; struct dentry *d; + struct user_namespace *userns; IMustLock(dir); @@ -273,9 +276,10 @@ int vfsub_symlink(struct inode *dir, struct path *path, const char *symname) path->dentry = d; if (unlikely(err)) goto out; + userns = mnt_user_ns(path->mnt); lockdep_off(); - err = vfs_symlink(dir, path->dentry, symname); + err = vfs_symlink(userns, dir, path->dentry, symname); lockdep_on(); if (!err) { struct path tmp = *path; @@ -297,6 +301,7 @@ int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev) { int err; struct dentry *d; + struct user_namespace *userns; IMustLock(dir); @@ -306,9 +311,10 @@ int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev) path->dentry = d; if (unlikely(err)) goto out; + userns = mnt_user_ns(path->mnt); lockdep_off(); - err = vfs_mknod(dir, path->dentry, mode, dev); + err = vfs_mknod(userns, dir, path->dentry, mode, dev); lockdep_on(); if (!err) { struct path tmp = *path; @@ -341,6 +347,7 @@ int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path, { int err; struct dentry *d; + struct user_namespace *userns; IMustLock(dir); @@ -355,9 +362,10 @@ int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path, path->dentry = d; if (unlikely(err)) goto out; + userns = mnt_user_ns(path->mnt); lockdep_off(); - err = vfs_link(src_dentry, dir, path->dentry, delegated_inode); + err = vfs_link(src_dentry, userns, dir, path->dentry, delegated_inode); lockdep_on(); if (!err) { struct path tmp = *path; @@ -383,6 +391,7 @@ int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, struct inode **delegated_inode, unsigned int flags) { int err; + struct renamedata rd; struct path tmp = { .mnt = path->mnt }; @@ -399,9 +408,16 @@ int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, if (unlikely(err)) goto out; + rd.old_mnt_userns = mnt_user_ns(path->mnt); + rd.old_dir = src_dir; + rd.old_dentry = src_dentry; + rd.new_mnt_userns = rd.old_mnt_userns; + rd.new_dir = dir; + rd.new_dentry = path->dentry; + rd.delegated_inode = delegated_inode; + rd.flags = flags; lockdep_off(); - err = vfs_rename(src_dir, src_dentry, dir, path->dentry, - delegated_inode, flags); + err = vfs_rename(&rd); lockdep_on(); if (!err) { int did; @@ -425,6 +441,7 @@ int vfsub_mkdir(struct inode *dir, struct path *path, int mode) { int err; struct dentry *d; + struct user_namespace *userns; IMustLock(dir); @@ -434,9 +451,10 @@ int vfsub_mkdir(struct inode *dir, struct path *path, int mode) path->dentry = d; if (unlikely(err)) goto out; + userns = mnt_user_ns(path->mnt); lockdep_off(); - err = vfs_mkdir(dir, path->dentry, mode); + err = vfs_mkdir(userns, dir, path->dentry, mode); lockdep_on(); if (!err) { struct path tmp = *path; @@ -458,6 +476,7 @@ int vfsub_rmdir(struct inode *dir, struct path *path) { int err; struct dentry *d; + struct user_namespace *userns; IMustLock(dir); @@ -467,9 +486,10 @@ int vfsub_rmdir(struct inode *dir, struct path *path) path->dentry = d; if (unlikely(err)) goto out; + userns = mnt_user_ns(path->mnt); lockdep_off(); - err = vfs_rmdir(dir, path->dentry); + err = vfs_rmdir(userns, dir, path->dentry); lockdep_on(); if (!err) { struct path tmp = { @@ -627,6 +647,7 @@ int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, int err; struct inode *h_inode; struct super_block *h_sb; + struct user_namespace *h_userns; if (!h_file) { err = vfsub_truncate(h_path, length); @@ -642,8 +663,10 @@ int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, if (!err) err = security_path_truncate(h_path); if (!err) { + h_userns = mnt_user_ns(h_path->mnt); lockdep_off(); - err = do_truncate(h_path->dentry, length, attr, h_file); + err = do_truncate(h_userns, h_path->dentry, length, attr, + h_file); lockdep_on(); } lockdep_off(); @@ -672,8 +695,10 @@ static void au_call_vfsub_mkdir(void *args) int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode) { int err, do_sio, wkq_err; + struct user_namespace *userns; - do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); + userns = mnt_user_ns(path->mnt); + do_sio = au_test_h_perm_sio(userns, dir, MAY_EXEC | MAY_WRITE); if (!do_sio) { lockdep_off(); err = vfsub_mkdir(dir, path, mode); @@ -708,8 +733,10 @@ static void au_call_vfsub_rmdir(void *args) int vfsub_sio_rmdir(struct inode *dir, struct path *path) { int err, do_sio, wkq_err; + struct user_namespace *userns; - do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); + userns = mnt_user_ns(path->mnt); + do_sio = au_test_h_perm_sio(userns, dir, MAY_EXEC | MAY_WRITE); if (!do_sio) { lockdep_off(); err = vfsub_rmdir(dir, path); @@ -741,14 +768,16 @@ static void call_notify_change(void *args) { struct notify_change_args *a = args; struct inode *h_inode; + struct user_namespace *userns; h_inode = d_inode(a->path->dentry); IMustLock(h_inode); *a->errp = -EPERM; if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { + userns = mnt_user_ns(a->path->mnt); lockdep_off(); - *a->errp = notify_change(a->path->dentry, a->ia, + *a->errp = notify_change(userns, a->path->dentry, a->ia, a->delegated_inode); lockdep_on(); if (!*a->errp) @@ -805,6 +834,7 @@ static void call_unlink(void *args) struct unlink_args *a = args; struct dentry *d = a->path->dentry; struct inode *h_inode; + struct user_namespace *userns; const int stop_sillyrename = (au_test_nfs(d->d_sb) && au_dcount(d) == 1); @@ -824,8 +854,9 @@ static void call_unlink(void *args) ihold(h_inode); } + userns = mnt_user_ns(a->path->mnt); lockdep_off(); - *a->errp = vfs_unlink(a->dir, d, a->delegated_inode); + *a->errp = vfs_unlink(userns, a->dir, d, a->delegated_inode); lockdep_on(); if (!*a->errp) { struct path tmp = { diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h index 7d8993052cd50f..aeed091eca50cd 100644 --- a/fs/aufs/vfsub.h +++ b/fs/aufs/vfsub.h @@ -221,17 +221,19 @@ static inline int vfsub_update_time(struct inode *h_inode, } #ifdef CONFIG_FS_POSIX_ACL -static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode) +static inline int vfsub_acl_chmod(struct user_namespace *h_userns, + struct inode *h_inode, umode_t h_mode) { int err; - err = posix_acl_chmod(h_inode, h_mode); + err = posix_acl_chmod(h_userns, h_inode, h_mode); if (err == -EOPNOTSUPP) err = 0; return err; } #else -AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode); +AuStubInt0(vfsub_acl_chmod, struct user_namespace *h_userns, + struct inode *h_inode, umode_t h_mode); #endif long vfsub_splice_to(struct file *in, loff_t *ppos, @@ -314,24 +316,26 @@ static inline int vfsub_getattr(const struct path *path, struct kstat *st) /* ---------------------------------------------------------------------- */ -static inline int vfsub_setxattr(struct dentry *dentry, const char *name, +static inline int vfsub_setxattr(struct user_namespace *userns, + struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { int err; lockdep_off(); - err = vfs_setxattr(dentry, name, value, size, flags); + err = vfs_setxattr(userns, dentry, name, value, size, flags); lockdep_on(); return err; } -static inline int vfsub_removexattr(struct dentry *dentry, const char *name) +static inline int vfsub_removexattr(struct user_namespace *userns, + struct dentry *dentry, const char *name) { int err; lockdep_off(); - err = vfs_removexattr(dentry, name); + err = vfs_removexattr(userns, dentry, name); lockdep_on(); return err; diff --git a/fs/aufs/whout.c b/fs/aufs/whout.c index 9363954c4b06de..ea28011bc0c3dd 100644 --- a/fs/aufs/whout.c +++ b/fs/aufs/whout.c @@ -51,7 +51,8 @@ int au_wh_name_alloc(struct qstr *wh, const struct qstr *name) * test if the @wh_name exists under @h_parent. * @try_sio specifies the necessary of super-io. */ -int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio) +int au_wh_test(struct user_namespace *h_userns, struct dentry *h_parent, + struct qstr *wh_name, int try_sio) { int err; struct dentry *wh_dentry; @@ -59,7 +60,7 @@ int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio) if (!try_sio) wh_dentry = vfsub_lkup_one(wh_name, h_parent); else - wh_dentry = au_sio_lkup_one(wh_name, h_parent); + wh_dentry = au_sio_lkup_one(h_userns, wh_name, h_parent); err = PTR_ERR(wh_dentry); if (IS_ERR(wh_dentry)) { if (err == -ENAMETOOLONG) @@ -88,14 +89,14 @@ int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio) /* * test if the @h_dentry sets opaque or not. */ -int au_diropq_test(struct dentry *h_dentry) +int au_diropq_test(struct user_namespace *h_userns, struct dentry *h_dentry) { int err; struct inode *h_dir; h_dir = d_inode(h_dentry); - err = au_wh_test(h_dentry, &diropq_name, - au_test_h_perm_sio(h_dir, MAY_EXEC)); + err = au_wh_test(h_userns, h_dentry, &diropq_name, + au_test_h_perm_sio(h_userns, h_dir, MAY_EXEC)); return err; } @@ -112,6 +113,7 @@ struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, /* strict atomic_t is unnecessary here */ static unsigned short cnt; struct qstr qs; + struct user_namespace *h_userns; BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN); @@ -135,10 +137,11 @@ struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, *p++ = '.'; AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN); + h_userns = au_br_userns(br); qs.name = name; for (i = 0; i < 3; i++) { sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++); - dentry = au_sio_lkup_one(&qs, h_parent); + dentry = au_sio_lkup_one(h_userns, &qs, h_parent); if (IS_ERR(dentry) || d_is_negative(dentry)) goto out_name; dput(dentry); @@ -737,9 +740,12 @@ struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, unsigned int flags) { struct dentry *diropq, *h_dentry; + struct user_namespace *h_userns; + h_userns = au_sbr_userns(dentry->d_sb, bindex); h_dentry = au_h_dptr(dentry, bindex); - if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE)) + if (!au_test_h_perm_sio(h_userns, d_inode(h_dentry), + MAY_EXEC | MAY_WRITE)) diropq = do_diropq(dentry, bindex, flags); else { int wkq_err; @@ -925,11 +931,13 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, struct path h_tmp; struct inode *wh_inode, *h_dir; struct au_branch *br; + struct user_namespace *h_userns; h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ IMustLock(h_dir); br = au_sbr(dir->i_sb, bindex); + h_userns = au_br_userns(br); wh_inode = d_inode(wh_dentry); inode_lock_nested(wh_inode, AuLsc_I_CHILD); @@ -937,7 +945,7 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, * someone else might change some whiteouts while we were sleeping. * it means this whlist may have an obsoleted entry. */ - if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE)) + if (!au_test_h_perm_sio(h_userns, wh_inode, MAY_EXEC | MAY_WRITE)) err = del_wh_children(wh_dentry, whlist, bindex, br); else { int wkq_err; diff --git a/fs/aufs/whout.h b/fs/aufs/whout.h index dc4eb41e70dd34..bc159641173974 100644 --- a/fs/aufs/whout.h +++ b/fs/aufs/whout.h @@ -16,8 +16,9 @@ /* whout.c */ int au_wh_name_alloc(struct qstr *wh, const struct qstr *name); -int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio); -int au_diropq_test(struct dentry *h_dentry); +int au_wh_test(struct user_namespace *h_userns, struct dentry *h_parent, + struct qstr *wh_name, int try_sio); +int au_diropq_test(struct user_namespace *h_userns, struct dentry *h_dentry); struct au_branch; struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, struct qstr *prefix); diff --git a/fs/aufs/xattr.c b/fs/aufs/xattr.c index a71145b741b1a7..cfdd9928c0d242 100644 --- a/fs/aufs/xattr.c +++ b/fs/aufs/xattr.c @@ -51,21 +51,26 @@ static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags) static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1; -static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, +static int au_do_cpup_xattr(struct path *h_dst, struct path *h_src, char *name, char **buf, unsigned int ignore_flags, unsigned int verbose) { int err; ssize_t ssz; struct inode *h_idst; + struct dentry *h_dst_dentry, *h_src_dentry; + struct user_namespace *h_dst_userns, *h_src_userns; - ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS); + h_src_userns = mnt_user_ns(h_src->mnt); + h_src_dentry = h_src->dentry; + ssz = vfs_getxattr_alloc(h_src_userns, h_src_dentry, name, buf, 0, + GFP_NOFS); err = ssz; if (unlikely(err <= 0)) { if (err == -ENODATA || (err == -EOPNOTSUPP && ((ignore_flags & au_xattr_out_of_list) - || (au_test_nfs_noacl(d_inode(h_src)) + || (au_test_nfs_noacl(d_inode(h_src_dentry)) && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) || !strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT)))) @@ -77,9 +82,12 @@ static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, } /* unlock it temporary */ - h_idst = d_inode(h_dst); + h_dst_userns = mnt_user_ns(h_dst->mnt); + h_dst_dentry = h_dst->dentry; + h_idst = d_inode(h_dst_dentry); inode_unlock(h_idst); - err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0); + err = vfsub_setxattr(h_dst_userns, h_dst_dentry, name, *buf, ssz, + /*flags*/0); inode_lock_nested(h_idst, AuLsc_I_CHILD2); if (unlikely(err)) { if (verbose || au_debug_test()) @@ -91,25 +99,28 @@ static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, return err; } -int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, +int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags, unsigned int verbose) { int err, unlocked, acl_access, acl_default; ssize_t ssz; + struct dentry *h_dst_dentry, *h_src_dentry; struct inode *h_isrc, *h_idst; char *value, *p, *o, *e; /* try stopping to update the source inode while we are referencing */ /* there should not be the parent-child relationship between them */ - h_isrc = d_inode(h_src); - h_idst = d_inode(h_dst); + h_dst_dentry = h_dst->dentry; + h_idst = d_inode(h_dst_dentry); + h_src_dentry = h_src->dentry; + h_isrc = d_inode(h_src_dentry); inode_unlock(h_idst); inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD); inode_lock_nested(h_idst, AuLsc_I_CHILD2); unlocked = 0; /* some filesystems don't list POSIX ACL, for example tmpfs */ - ssz = vfs_listxattr(h_src, NULL, 0); + ssz = vfs_listxattr(h_src_dentry, NULL, 0); err = ssz; if (unlikely(err < 0)) { AuTraceErr(err); @@ -128,7 +139,7 @@ int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, o = p; if (unlikely(!p)) goto out; - err = vfs_listxattr(h_src, p, ssz); + err = vfs_listxattr(h_src_dentry, p, ssz); } inode_unlock_shared(h_isrc); unlocked = 1; @@ -242,7 +253,7 @@ static ssize_t au_lgxattr(struct dentry *dentry, struct inode *inode, break; case AU_XATTR_GET: AuDebugOn(d_is_negative(h_path.dentry)); - err = vfs_getxattr(h_path.dentry, + err = vfs_getxattr(mnt_user_ns(h_path.mnt), h_path.dentry, arg->u.get.name, arg->u.get.value, arg->u.get.size); break; @@ -314,6 +325,7 @@ static int au_xattr_get(const struct xattr_handler *handler, } static int au_xattr_set(const struct xattr_handler *handler, + struct user_namespace *userns, struct dentry *dentry, struct inode *inode, const char *name, const void *value, size_t size, int flags) diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c index 753e92a3d6d784..ee3d3f2e6ac750 100644 --- a/fs/aufs/xino.c +++ b/fs/aufs/xino.c @@ -245,7 +245,7 @@ struct file *au_xino_create2(struct super_block *sb, struct path *base, } /* no need to mnt_want_write() since we call dentry_open() later */ - err = vfs_create(dir, path.dentry, 0666, NULL); + err = vfs_create(mnt_user_ns(base->mnt), dir, path.dentry, 0666, NULL); if (unlikely(err)) { file = ERR_PTR(err); pr_err("%pd create err %d\n", dentry, err);