ovl: store lower path in ovl_inode
authorAmir Goldstein <amir73il@gmail.com>
Mon, 4 Apr 2022 10:51:53 +0000 (12:51 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 31 Dec 2022 12:14:00 +0000 (13:14 +0100)
[ Upstream commit ffa5723c6d259b3191f851a50a98d0352b345b39 ]

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: b306e90ffabd ("ovl: remove privs in ovl_copyfile()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/overlayfs/inode.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/super.c
fs/overlayfs/util.c

index 1f36158c7dbe2f8782a2dcb6f15a4f0c4bbef28c..06479bc88b7ed5370de9f446cb0eef33917f44dd 100644 (file)
@@ -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);
index 2cd5741c873b60592a139273017b669075bac72f..27f22196266539a868a5bf25bda1d07699ca1a31 100644 (file)
@@ -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);
index 63efee554f69a7c1e862650d8f7b388576fda2cd..b2d64f3c974bbd1af575ca89e89b08372cb0794f 100644 (file)
@@ -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;
index 9837aaf9caf187b74bba00cb7f3d19b9a8ddc7b7..e2ed38c5f721073ff31fa462c5812251e60cdc93 100644 (file)
@@ -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);
 
@@ -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
index f48284a2a89600d32ef96ec600cdbc47b04781d4..2567918dc6842b9fcd724610768df30431400bd4 100644 (file)
@@ -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);
@@ -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)