From: Christian Brauner <christian.brauner@xxxxxxxxxx> Various filesystems use the lookup_positive_unlocked() helper to lookup a single path component relative to a well-known starting point. Allow such filesystems to support idmapped mounts by enabling lookup_positive_unlocked() to take the idmap into account when calling inode_permission(). This change is a required to let btrfs (and other filesystems) support idmapped mounts. Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: linux-fsdevel@xxxxxxxxxxxxxxx Signed-off-by: Christian Brauner <christian.brauner@xxxxxxxxxx> --- fs/cifs/cifsfs.c | 3 ++- fs/debugfs/inode.c | 3 ++- fs/kernfs/mount.c | 4 ++-- fs/namei.c | 7 ++++--- fs/nfsd/nfs3xdr.c | 3 ++- fs/nfsd/nfs4xdr.c | 3 ++- fs/overlayfs/namei.c | 10 ++++++---- fs/quota/dquot.c | 3 ++- include/linux/namei.h | 3 ++- 9 files changed, 24 insertions(+), 15 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 64b71c4e2a9d..b61643427e46 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -804,7 +804,8 @@ cifs_get_root(struct smb3_fs_context *ctx, struct super_block *sb) while (*s && *s != sep) s++; - child = lookup_positive_unlocked(p, dentry, s - p); + child = lookup_positive_unlocked(&init_user_ns, p, + dentry, s - p); dput(dentry); dentry = child; } while (!IS_ERR(dentry)); diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 92db343f35f4..eda31d0966a5 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -307,7 +307,8 @@ struct dentry *debugfs_lookup(const char *name, struct dentry *parent) if (!parent) parent = debugfs_mount->mnt_root; - dentry = lookup_positive_unlocked(name, parent, strlen(name)); + dentry = lookup_positive_unlocked(&init_user_ns, name, + parent, strlen(name)); if (IS_ERR(dentry)) return NULL; return dentry; diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index 9dc7e7a64e10..20b8617e619b 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c @@ -223,8 +223,8 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, dput(dentry); return ERR_PTR(-EINVAL); } - dtmp = lookup_positive_unlocked(kntmp->name, dentry, - strlen(kntmp->name)); + dtmp = lookup_positive_unlocked(&init_user_ns, kntmp->name, + dentry, strlen(kntmp->name)); dput(dentry); if (IS_ERR(dtmp)) return dtmp; diff --git a/fs/namei.c b/fs/namei.c index 53561311b492..68489c23bc44 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2706,10 +2706,11 @@ EXPORT_SYMBOL(lookup_one_len_unlocked); * need to be very careful; pinned positives have ->d_inode stable, so * this one avoids such problems. */ -struct dentry *lookup_positive_unlocked(const char *name, - struct dentry *base, int len) +struct dentry *lookup_positive_unlocked(struct user_namespace *mnt_userns, + const char *name, struct dentry *base, + int len) { - struct dentry *ret = lookup_one_len_unlocked(&init_user_ns, name, base, len); + struct dentry *ret = lookup_one_len_unlocked(mnt_userns, name, base, len); if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) { dput(ret); ret = ERR_PTR(-ENOENT); diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 0a5ebc52e6a9..0fad12be94cd 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -1109,7 +1109,8 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, } else dchild = dget(dparent); } else - dchild = lookup_positive_unlocked(name, dparent, namlen); + dchild = lookup_positive_unlocked(&init_user_ns, name, + dparent, namlen); if (IS_ERR(dchild)) return rv; if (d_mountpoint(dchild)) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 7abeccb975b2..a0425d120e6a 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3413,7 +3413,8 @@ nfsd4_encode_dirent_fattr(struct xdr_stream *xdr, struct nfsd4_readdir *cd, __be32 nfserr; int ignore_crossmnt = 0; - dentry = lookup_positive_unlocked(name, cd->rd_fhp->fh_dentry, namlen); + dentry = lookup_positive_unlocked(&init_user_ns, name, + cd->rd_fhp->fh_dentry, namlen); if (IS_ERR(dentry)) return nfserrno(PTR_ERR(dentry)); diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 291985b79a6d..52721af35dcf 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -673,7 +673,8 @@ struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh) if (err) return ERR_PTR(err); - index = lookup_positive_unlocked(name.name, ofs->indexdir, name.len); + index = lookup_positive_unlocked(&init_user_ns, name.name, + ofs->indexdir, name.len); kfree(name.name); if (IS_ERR(index)) { if (PTR_ERR(index) == -ENOENT) @@ -705,7 +706,8 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper, if (err) return ERR_PTR(err); - index = lookup_positive_unlocked(name.name, ofs->indexdir, name.len); + index = lookup_positive_unlocked(&init_user_ns, name.name, + ofs->indexdir, name.len); if (IS_ERR(index)) { err = PTR_ERR(index); if (err == -ENOENT) { @@ -1164,8 +1166,8 @@ bool ovl_lower_positive(struct dentry *dentry) struct dentry *this; struct dentry *lowerdir = poe->lowerstack[i].dentry; - this = lookup_positive_unlocked(name->name, lowerdir, - name->len); + this = lookup_positive_unlocked(&init_user_ns, name->name, + lowerdir, name->len); if (IS_ERR(this)) { switch (PTR_ERR(this)) { case -ENOENT: diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 22d904bde6ab..8cdd6df7597a 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2487,7 +2487,8 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name, struct dentry *dentry; int error; - dentry = lookup_positive_unlocked(qf_name, sb->s_root, strlen(qf_name)); + dentry = lookup_positive_unlocked(&init_user_ns, qf_name, + sb->s_root, strlen(qf_name)); if (IS_ERR(dentry)) return PTR_ERR(dentry); diff --git a/include/linux/namei.h b/include/linux/namei.h index b4073e36450a..c177edfb2364 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -69,7 +69,8 @@ extern struct dentry *lookup_one_len(struct user_namespace *mnt_userns, const char *, struct dentry *, int); extern struct dentry *lookup_one_len_unlocked(struct user_namespace *, const char *, struct dentry *, int); -extern struct dentry *lookup_positive_unlocked(const char *, struct dentry *, int); +extern struct dentry *lookup_positive_unlocked(struct user_namespace *, + const char *, struct dentry *, int); extern int follow_down_one(struct path *); extern int follow_down(struct path *); -- 2.30.2