Commit 98a37409 authored by Andy Whitcroft's avatar Andy Whitcroft Committed by Tim Gardner

UBUNTU: SAUCE: overlayfs: when copying up and reading directories ensure mounter had permissions V2

When copying up files and reading directory contents ensure the mounter has
permissions for the operation over the consituent parts (lower and upper).
Where we are in a namespace this ensures that the mounter (root in that
namespace) has permissions over the files and directories, preventing
exposure of protected files and directory contents.

CVE-2015-1328
Acked-by: default avatarTyler Hicks <tyhicks@canonical.com>
Acked-by: default avatarSerge E. Hallyn <serge.hallyn@ubuntu.com>
Signed-off-by: default avatarAndy Whitcroft <apw@canonical.com>
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>
parent 204bb1c7
......@@ -309,9 +309,17 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
if (WARN_ON(!workdir))
return -EROFS;
err = ovl_dentry_root_may(dentry, lowerpath, MAY_READ);
if (err)
return err;
ovl_path_upper(parent, &parentpath);
upperdir = parentpath.dentry;
err = ovl_dentry_root_may(dentry, &parentpath, MAY_WRITE);
if (err)
return err;
err = vfs_getattr(&parentpath, &pstat);
if (err)
return err;
......
......@@ -175,6 +175,7 @@ struct file *ovl_path_open(struct path *path, int flags);
struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry,
struct kstat *stat, const char *link);
int ovl_dentry_root_may(struct dentry *dentry, struct path *realpath, int mode);
/* readdir.c */
extern const struct file_operations ovl_dir_operations;
......
......@@ -14,6 +14,7 @@
#include <linux/xattr.h>
#include <linux/rbtree.h>
#include <linux/security.h>
#include <linux/sched.h>
#include <linux/cred.h>
#include "overlayfs.h"
......@@ -298,6 +299,10 @@ static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list)
for (idx = 0; idx != -1; idx = next) {
next = ovl_path_next(idx, dentry, &realpath);
err = ovl_dentry_root_may(dentry, &realpath, MAY_READ);
if (err)
break;
if (next != -1) {
err = ovl_dir_read(&realpath, &rdd);
if (err)
......@@ -371,8 +376,13 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
if (!ctx->pos)
ovl_dir_reset(file);
if (od->is_real)
if (od->is_real) {
int res = ovl_dentry_root_may(dentry, &(od->realfile->f_path), MAY_READ);
if (res)
return res;
return iterate_dir(od->realfile, ctx);
}
if (!od->cache) {
struct ovl_dir_cache *cache;
......
......@@ -43,6 +43,7 @@ struct ovl_fs {
int legacy;
/* pathnames of lower and upper dirs, for show_options */
struct ovl_config config;
struct cred *mounter_creds;
};
struct ovl_dir_cache;
......@@ -238,6 +239,22 @@ u64 ovl_dentry_version_get(struct dentry *dentry)
return oe->version;
}
int ovl_dentry_root_may(struct dentry *dentry, struct path *realpath, int mode)
{
const struct cred *old_cred;
int err = 0;
struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
old_cred = override_creds(ofs->mounter_creds);
if (inode_permission(realpath->dentry->d_inode, mode))
err = -EACCES;
revert_creds(old_cred);
return err;
}
#ifdef CONFIG_OVERLAY_FS_V1
int ovl_config_legacy(struct dentry *dentry)
{
......@@ -586,6 +603,7 @@ static void ovl_put_super(struct super_block *sb)
struct ovl_fs *ufs = sb->s_fs_info;
unsigned i;
put_cred(ufs->mounter_creds);
dput(ufs->workdir);
mntput(ufs->upper_mnt);
for (i = 0; i < ufs->numlower; i++)
......@@ -1085,6 +1103,11 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
if (!root_dentry)
goto out_free_oe;
/* Record the mounter. */
ufs->mounter_creds = prepare_creds();
if (!ufs->mounter_creds)
goto out_put_root;
mntput(upperpath.mnt);
for (i = 0; i < numlower; i++)
mntput(stack[i].mnt);
......@@ -1110,6 +1133,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
return 0;
out_put_root:
dput(root_dentry);
out_free_oe:
kfree(oe);
out_put_lower_mnt:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment