Skip to content

Commit

Permalink
ovl: handle idmappings for layer lookup
Browse files Browse the repository at this point in the history
Make the two places where lookup helpers can be called either on lower
or upper layers take the mount's idmapping into account. To this end we
pass down the mount in struct ovl_lookup_data. It can later also be used
to construct struct path for various other helpers. This is needed to
support idmapped base layers with overlay.

Cc: <linux-unionfs@vger.kernel.org>
Tested-by: Giuseppe Scrivano <gscrivan@redhat.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
  • Loading branch information
Christian Brauner authored and Miklos Szeredi committed Apr 28, 2022
1 parent 50db8d0 commit ba9ea77
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 11 deletions.
5 changes: 5 additions & 0 deletions fs/overlayfs/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,11 @@ static struct dentry *ovl_lookup_real_one(struct dentry *connected,
* pointer because we hold no lock on the real dentry.
*/
take_dentry_name_snapshot(&name, real);
/*
* No mnt_userns handling here: it's an internal lookup. Could skip
* permission checking altogether, but for now just use non-mnt_userns
* transformed ids.
*/
this = lookup_one_len(name.name.name, connected, name.name.len);
release_dentry_name_snapshot(&name);
err = PTR_ERR(this);
Expand Down
14 changes: 8 additions & 6 deletions fs/overlayfs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,12 @@ static bool ovl_is_opaquedir(struct ovl_fs *ofs, struct path *path)
return ovl_path_check_dir_xattr(ofs, path, OVL_XATTR_OPAQUE);
}

static struct dentry *ovl_lookup_positive_unlocked(const char *name,
static struct dentry *ovl_lookup_positive_unlocked(struct ovl_lookup_data *d,
const char *name,
struct dentry *base, int len,
bool drop_negative)
{
struct dentry *ret = lookup_one_len_unlocked(name, base, len);
struct dentry *ret = lookup_one_unlocked(mnt_user_ns(d->mnt), name, base, len);

if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
if (drop_negative && ret->d_lockref.count == 1) {
Expand All @@ -229,7 +230,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
int err;
bool last_element = !post[0];

this = ovl_lookup_positive_unlocked(name, base, namelen, drop_negative);
this = ovl_lookup_positive_unlocked(d, name, base, namelen, drop_negative);
if (IS_ERR(this)) {
err = PTR_ERR(this);
this = NULL;
Expand Down Expand Up @@ -709,7 +710,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_one_positive_unlocked(ovl_upper_mnt_userns(ofs), name.name,
ofs->indexdir, name.len);
if (IS_ERR(index)) {
err = PTR_ERR(index);
if (err == -ENOENT) {
Expand Down Expand Up @@ -1174,8 +1176,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_one_positive_unlocked(mnt_user_ns(poe->lowerstack[i].layer->mnt),
name->name, lowerdir, name->len);
if (IS_ERR(this)) {
switch (PTR_ERR(this)) {
case -ENOENT:
Expand Down
10 changes: 5 additions & 5 deletions fs/overlayfs/readdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,11 @@ static int ovl_fill_merge(struct dir_context *ctx, const char *name,
return ovl_fill_lowest(rdd, name, namelen, offset, ino, d_type);
}

static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
static int ovl_check_whiteouts(struct path *path, struct ovl_readdir_data *rdd)
{
int err;
struct ovl_cache_entry *p;
struct dentry *dentry;
struct dentry *dentry, *dir = path->dentry;
const struct cred *old_cred;

old_cred = ovl_override_creds(rdd->dentry->d_sb);
Expand All @@ -278,7 +278,7 @@ static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
while (rdd->first_maybe_whiteout) {
p = rdd->first_maybe_whiteout;
rdd->first_maybe_whiteout = p->next_maybe_whiteout;
dentry = lookup_one_len(p->name, dir, p->len);
dentry = lookup_one(mnt_user_ns(path->mnt), p->name, dir, p->len);
if (!IS_ERR(dentry)) {
p->is_whiteout = ovl_is_whiteout(dentry);
dput(dentry);
Expand Down Expand Up @@ -312,7 +312,7 @@ static inline int ovl_dir_read(struct path *realpath,
} while (!err && rdd->count);

if (!err && rdd->first_maybe_whiteout && rdd->dentry)
err = ovl_check_whiteouts(realpath->dentry, rdd);
err = ovl_check_whiteouts(realpath, rdd);

fput(realfile);

Expand Down Expand Up @@ -479,7 +479,7 @@ static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p)
goto get;
}
}
this = lookup_one_len(p->name, dir, p->len);
this = lookup_one(mnt_user_ns(path->mnt), p->name, dir, p->len);
if (IS_ERR_OR_NULL(this) || !this->d_inode) {
/* Mark a stale entry */
p->is_whiteout = true;
Expand Down

0 comments on commit ba9ea77

Please sign in to comment.