ovl: handle idmappings in layer open helpers
authorChristian Brauner <brauner@kernel.org>
Mon, 4 Apr 2022 10:51:56 +0000 (12:51 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Thu, 28 Apr 2022 14:31:12 +0000 (16:31 +0200)
In earlier patches we already passed down the relevant upper or lower
path to ovl_open_realfile(). Now let the open helpers actually take the
idmapping of the relevant mount into account when checking permissions.
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>
fs/overlayfs/file.c
fs/overlayfs/util.c

index 1d9bcc5..3fac8a0 100644 (file)
@@ -42,6 +42,7 @@ static struct file *ovl_open_realfile(const struct file *file,
 {
        struct inode *realinode = d_inode(realpath->dentry);
        struct inode *inode = file_inode(file);
+       struct user_namespace *real_mnt_userns;
        struct file *realfile;
        const struct cred *old_cred;
        int flags = file->f_flags | OVL_OPEN_FLAGS;
@@ -52,11 +53,12 @@ static struct file *ovl_open_realfile(const struct file *file,
                acc_mode |= MAY_APPEND;
 
        old_cred = ovl_override_creds(inode->i_sb);
-       err = inode_permission(&init_user_ns, realinode, MAY_OPEN | acc_mode);
+       real_mnt_userns = mnt_user_ns(realpath->mnt);
+       err = inode_permission(real_mnt_userns, realinode, MAY_OPEN | acc_mode);
        if (err) {
                realfile = ERR_PTR(err);
        } else {
-               if (!inode_owner_or_capable(&init_user_ns, realinode))
+               if (!inode_owner_or_capable(real_mnt_userns, realinode))
                        flags &= ~O_NOATIME;
 
                realfile = open_with_fake_path(&file->f_path, flags, realinode,
index 10032f7..87f811c 100644 (file)
@@ -493,6 +493,7 @@ bool ovl_is_whiteout(struct dentry *dentry)
 struct file *ovl_path_open(struct path *path, int flags)
 {
        struct inode *inode = d_inode(path->dentry);
+       struct user_namespace *real_mnt_userns = mnt_user_ns(path->mnt);
        int err, acc_mode;
 
        if (flags & ~(O_ACCMODE | O_LARGEFILE))
@@ -509,12 +510,12 @@ struct file *ovl_path_open(struct path *path, int flags)
                BUG();
        }
 
-       err = inode_permission(&init_user_ns, inode, acc_mode | MAY_OPEN);
+       err = inode_permission(real_mnt_userns, inode, acc_mode | MAY_OPEN);
        if (err)
                return ERR_PTR(err);
 
        /* O_NOATIME is an optimization, don't fail if not permitted */
-       if (inode_owner_or_capable(&init_user_ns, inode))
+       if (inode_owner_or_capable(real_mnt_userns, inode))
                flags |= O_NOATIME;
 
        return dentry_open(path, flags, current_cred());