Skip to content

Commit

Permalink
ovl: store lower path in ovl_inode
Browse files Browse the repository at this point in the history
[ Upstream commit ffa5723 ]

Create some ovl_i_* helpers to get real path from ovl inode. Instead of
just stashing struct inode for the lower layer we stash struct path for
the lower layer. The helpers allow to retrieve a struct path for the
relevant upper or lower layer. This will be used when retrieving
information based on struct inode when copying up inode attributes from
upper or lower inodes to ovl inodes and when checking permissions in
ovl_permission() in following patches. 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: Christian Brauner (Microsoft) <brauner@kernel.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Stable-dep-of: b306e90 ("ovl: remove privs in ovl_copyfile()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
amir73il authored and gregkh committed Dec 31, 2022
1 parent 163c5bb commit a548438
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 8 deletions.
11 changes: 7 additions & 4 deletions fs/overlayfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -777,13 +777,16 @@ void ovl_inode_init(struct inode *inode, struct ovl_inode_params *oip,
unsigned long ino, int fsid)
{
struct inode *realinode;
struct ovl_inode *oi = OVL_I(inode);

if (oip->upperdentry)
OVL_I(inode)->__upperdentry = oip->upperdentry;
if (oip->lowerpath && oip->lowerpath->dentry)
OVL_I(inode)->lower = igrab(d_inode(oip->lowerpath->dentry));
oi->__upperdentry = oip->upperdentry;
if (oip->lowerpath && oip->lowerpath->dentry) {
oi->lowerpath.dentry = dget(oip->lowerpath->dentry);
oi->lowerpath.layer = oip->lowerpath->layer;
}
if (oip->lowerdata)
OVL_I(inode)->lowerdata = igrab(d_inode(oip->lowerdata));
oi->lowerdata = igrab(d_inode(oip->lowerdata));

realinode = ovl_inode_real(inode);
ovl_copyattr(realinode, inode);
Expand Down
2 changes: 2 additions & 0 deletions fs/overlayfs/overlayfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,12 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry);
void ovl_path_upper(struct dentry *dentry, struct path *path);
void ovl_path_lower(struct dentry *dentry, struct path *path);
void ovl_path_lowerdata(struct dentry *dentry, struct path *path);
void ovl_i_path_real(struct inode *inode, struct path *path);
enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path);
struct dentry *ovl_dentry_upper(struct dentry *dentry);
struct dentry *ovl_dentry_lower(struct dentry *dentry);
struct dentry *ovl_dentry_lowerdata(struct dentry *dentry);
const struct ovl_layer *ovl_i_layer_lower(struct inode *inode);
const struct ovl_layer *ovl_layer_lower(struct dentry *dentry);
struct dentry *ovl_dentry_real(struct dentry *dentry);
struct dentry *ovl_i_dentry_upper(struct inode *inode);
Expand Down
2 changes: 1 addition & 1 deletion fs/overlayfs/ovl_entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ struct ovl_inode {
unsigned long flags;
struct inode vfs_inode;
struct dentry *__upperdentry;
struct inode *lower;
struct ovl_path lowerpath;

/* synchronize copy up and more */
struct mutex lock;
Expand Down
5 changes: 3 additions & 2 deletions fs/overlayfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ static struct inode *ovl_alloc_inode(struct super_block *sb)
oi->version = 0;
oi->flags = 0;
oi->__upperdentry = NULL;
oi->lower = NULL;
oi->lowerpath.dentry = NULL;
oi->lowerpath.layer = NULL;
oi->lowerdata = NULL;
mutex_init(&oi->lock);

Expand All @@ -205,7 +206,7 @@ static void ovl_destroy_inode(struct inode *inode)
struct ovl_inode *oi = OVL_I(inode);

dput(oi->__upperdentry);
iput(oi->lower);
dput(oi->lowerpath.dentry);
if (S_ISDIR(inode->i_mode))
ovl_dir_cache_free(inode);
else
Expand Down
15 changes: 14 additions & 1 deletion fs/overlayfs/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,17 @@ struct dentry *ovl_i_dentry_upper(struct inode *inode)
return ovl_upperdentry_dereference(OVL_I(inode));
}

void ovl_i_path_real(struct inode *inode, struct path *path)
{
path->dentry = ovl_i_dentry_upper(inode);
if (!path->dentry) {
path->dentry = OVL_I(inode)->lowerpath.dentry;
path->mnt = OVL_I(inode)->lowerpath.layer->mnt;
} else {
path->mnt = ovl_upper_mnt(OVL_FS(inode->i_sb));
}
}

struct inode *ovl_inode_upper(struct inode *inode)
{
struct dentry *upperdentry = ovl_i_dentry_upper(inode);
Expand All @@ -245,7 +256,9 @@ struct inode *ovl_inode_upper(struct inode *inode)

struct inode *ovl_inode_lower(struct inode *inode)
{
return OVL_I(inode)->lower;
struct dentry *lowerdentry = OVL_I(inode)->lowerpath.dentry;

return lowerdentry ? d_inode(lowerdentry) : NULL;
}

struct inode *ovl_inode_real(struct inode *inode)
Expand Down

0 comments on commit a548438

Please sign in to comment.