ovl: switch to mounter creds in readdir
authorMiklos Szeredi <mszeredi@redhat.com>
Tue, 2 Jun 2020 20:20:25 +0000 (22:20 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 2 Jun 2020 20:20:25 +0000 (22:20 +0200)
In preparation for more permission checking, override credentials for
directory operations on the underlying filesystems.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/overlayfs/readdir.c

index 3bc9706..1621460 100644 (file)
@@ -743,8 +743,10 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
        struct ovl_dir_file *od = file->private_data;
        struct dentry *dentry = file->f_path.dentry;
        struct ovl_cache_entry *p;
        struct ovl_dir_file *od = file->private_data;
        struct dentry *dentry = file->f_path.dentry;
        struct ovl_cache_entry *p;
+       const struct cred *old_cred;
        int err;
 
        int err;
 
+       old_cred = ovl_override_creds(dentry->d_sb);
        if (!ctx->pos)
                ovl_dir_reset(file);
 
        if (!ctx->pos)
                ovl_dir_reset(file);
 
@@ -758,17 +760,20 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
                    (ovl_same_fs(dentry->d_sb) &&
                     (ovl_is_impure_dir(file) ||
                      OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent))))) {
                    (ovl_same_fs(dentry->d_sb) &&
                     (ovl_is_impure_dir(file) ||
                      OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent))))) {
-                       return ovl_iterate_real(file, ctx);
+                       err = ovl_iterate_real(file, ctx);
+               } else {
+                       err = iterate_dir(od->realfile, ctx);
                }
                }
-               return iterate_dir(od->realfile, ctx);
+               goto out;
        }
 
        if (!od->cache) {
                struct ovl_dir_cache *cache;
 
                cache = ovl_cache_get(dentry);
        }
 
        if (!od->cache) {
                struct ovl_dir_cache *cache;
 
                cache = ovl_cache_get(dentry);
+               err = PTR_ERR(cache);
                if (IS_ERR(cache))
                if (IS_ERR(cache))
-                       return PTR_ERR(cache);
+                       goto out;
 
                od->cache = cache;
                ovl_seek_cursor(od, ctx->pos);
 
                od->cache = cache;
                ovl_seek_cursor(od, ctx->pos);
@@ -780,7 +785,7 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
                        if (!p->ino) {
                                err = ovl_cache_update_ino(&file->f_path, p);
                                if (err)
                        if (!p->ino) {
                                err = ovl_cache_update_ino(&file->f_path, p);
                                if (err)
-                                       return err;
+                                       goto out;
                        }
                        if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
                                break;
                        }
                        if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
                                break;
@@ -788,7 +793,10 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
                od->cursor = p->l_node.next;
                ctx->pos++;
        }
                od->cursor = p->l_node.next;
                ctx->pos++;
        }
-       return 0;
+       err = 0;
+out:
+       revert_creds(old_cred);
+       return err;
 }
 
 static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin)
 }
 
 static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin)
@@ -834,7 +842,14 @@ out_unlock:
 static struct file *ovl_dir_open_realfile(struct file *file,
                                          struct path *realpath)
 {
 static struct file *ovl_dir_open_realfile(struct file *file,
                                          struct path *realpath)
 {
-       return ovl_path_open(realpath, O_RDONLY | (file->f_flags & O_LARGEFILE));
+       struct file *res;
+       const struct cred *old_cred;
+
+       old_cred = ovl_override_creds(file_inode(file)->i_sb);
+       res = ovl_path_open(realpath, O_RDONLY | (file->f_flags & O_LARGEFILE));
+       revert_creds(old_cred);
+
+       return res;
 }
 
 static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
 }
 
 static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,