Skip to content

Commit

Permalink
ovl: do operations on underlying file system in mounter's context
Browse files Browse the repository at this point in the history
Given we are now doing checks both on overlay inode as well underlying
inode, we should be able to do checks and operations on underlying file
system using mounter's context.

So modify all operations to do checks/operations on underlying dentry/inode
in the context of mounter.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
  • Loading branch information
Vivek Goyal authored and Miklos Szeredi committed Jul 29, 2016
1 parent c0ca3d7 commit 1175b6b
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 37 deletions.
60 changes: 29 additions & 31 deletions fs/overlayfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,12 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
int err;
enum ovl_path_type type;
struct path realpath;
const struct cred *old_cred;

type = ovl_path_real(dentry, &realpath);
old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_getattr(&realpath, stat);
revert_creds(old_cred);
if (err)
return err;

Expand Down Expand Up @@ -391,6 +394,8 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
{
int err;
struct inode *inode;
const struct cred *old_cred;
struct cred *override_cred;
struct kstat stat = {
.mode = mode,
.rdev = rdev,
Expand All @@ -405,28 +410,23 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
if (err)
goto out_iput;

if (!ovl_dentry_is_opaque(dentry)) {
err = ovl_create_upper(dentry, inode, &stat, link, hardlink);
} else {
const struct cred *old_cred;
struct cred *override_cred;

old_cred = ovl_override_creds(dentry->d_sb);

err = -ENOMEM;
override_cred = prepare_creds();
if (override_cred) {
override_cred->fsuid = old_cred->fsuid;
override_cred->fsgid = old_cred->fsgid;
put_cred(override_creds(override_cred));
put_cred(override_cred);

old_cred = ovl_override_creds(dentry->d_sb);
err = -ENOMEM;
override_cred = prepare_creds();
if (override_cred) {
override_cred->fsuid = old_cred->fsuid;
override_cred->fsgid = old_cred->fsgid;
put_cred(override_creds(override_cred));
put_cred(override_cred);

if (!ovl_dentry_is_opaque(dentry))
err = ovl_create_upper(dentry, inode, &stat, link,
hardlink);
else
err = ovl_create_over_whiteout(dentry, inode, &stat,
link, hardlink);
}
revert_creds(old_cred);
link, hardlink);
}

revert_creds(old_cred);
if (!err)
inode = NULL;
out_iput:
Expand Down Expand Up @@ -637,6 +637,8 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
{
enum ovl_path_type type;
int err;
const struct cred *old_cred;


err = ovl_check_sticky(dentry);
if (err)
Expand All @@ -651,15 +653,13 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
goto out_drop_write;

type = ovl_path_type(dentry);
if (OVL_TYPE_PURE_UPPER(type)) {
err = ovl_remove_upper(dentry, is_dir);
} else {
const struct cred *old_cred = ovl_override_creds(dentry->d_sb);

old_cred = ovl_override_creds(dentry->d_sb);
if (OVL_TYPE_PURE_UPPER(type))
err = ovl_remove_upper(dentry, is_dir);
else
err = ovl_remove_and_whiteout(dentry, is_dir);

revert_creds(old_cred);
}
revert_creds(old_cred);
out_drop_write:
ovl_drop_write(dentry);
out:
Expand Down Expand Up @@ -764,8 +764,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
old_opaque = !OVL_TYPE_PURE_UPPER(old_type);
new_opaque = !OVL_TYPE_PURE_UPPER(new_type);

if (old_opaque || new_opaque)
old_cred = ovl_override_creds(old->d_sb);
old_cred = ovl_override_creds(old->d_sb);

if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {
opaquedir = ovl_check_empty_and_clear(new);
Expand Down Expand Up @@ -895,8 +894,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
out_unlock:
unlock_rename(new_upperdir, old_upperdir);
out_revert_creds:
if (old_opaque || new_opaque)
revert_creds(old_cred);
revert_creds(old_cred);
out_drop_write:
ovl_drop_write(old);
out:
Expand Down
49 changes: 43 additions & 6 deletions fs/overlayfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
{
int err;
struct dentry *upperdentry;
const struct cred *old_cred;

/*
* Check for permissions before trying to copy-up. This is redundant
Expand Down Expand Up @@ -84,7 +85,9 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
attr->ia_valid &= ~ATTR_MODE;

inode_lock(upperdentry->d_inode);
old_cred = ovl_override_creds(dentry->d_sb);
err = notify_change(upperdentry, attr, NULL);
revert_creds(old_cred);
if (!err)
ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
inode_unlock(upperdentry->d_inode);
Expand All @@ -102,9 +105,14 @@ static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
struct path realpath;
const struct cred *old_cred;
int err;

ovl_path_real(dentry, &realpath);
return vfs_getattr(&realpath, stat);
old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_getattr(&realpath, stat);
revert_creds(old_cred);
return err;
}

int ovl_permission(struct inode *inode, int mask)
Expand Down Expand Up @@ -188,6 +196,8 @@ static const char *ovl_get_link(struct dentry *dentry,
{
struct dentry *realdentry;
struct inode *realinode;
const struct cred *old_cred;
const char *p;

if (!dentry)
return ERR_PTR(-ECHILD);
Expand All @@ -198,13 +208,18 @@ static const char *ovl_get_link(struct dentry *dentry,
if (WARN_ON(!realinode->i_op->get_link))
return ERR_PTR(-EPERM);

return realinode->i_op->get_link(realdentry, realinode, done);
old_cred = ovl_override_creds(dentry->d_sb);
p = realinode->i_op->get_link(realdentry, realinode, done);
revert_creds(old_cred);
return p;
}

static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
{
struct path realpath;
struct inode *realinode;
const struct cred *old_cred;
int err;

ovl_path_real(dentry, &realpath);
realinode = realpath.dentry->d_inode;
Expand All @@ -214,10 +229,12 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)

touch_atime(&realpath);

return realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
old_cred = ovl_override_creds(dentry->d_sb);
err = realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
revert_creds(old_cred);
return err;
}


static bool ovl_is_private_xattr(const char *name)
{
return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0;
Expand All @@ -229,6 +246,7 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode,
{
int err;
struct dentry *upperdentry;
const struct cred *old_cred;

err = ovl_want_write(dentry);
if (err)
Expand All @@ -243,7 +261,9 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode,
goto out_drop_write;

upperdentry = ovl_dentry_upper(dentry);
old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_setxattr(upperdentry, name, value, size, flags);
revert_creds(old_cred);

out_drop_write:
ovl_drop_write(dentry);
Expand All @@ -255,20 +275,28 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size)
{
struct dentry *realdentry = ovl_dentry_real(dentry);
ssize_t res;
const struct cred *old_cred;

if (ovl_is_private_xattr(name))
return -ENODATA;

return vfs_getxattr(realdentry, name, value, size);
old_cred = ovl_override_creds(dentry->d_sb);
res = vfs_getxattr(realdentry, name, value, size);
revert_creds(old_cred);
return res;
}

ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
{
struct dentry *realdentry = ovl_dentry_real(dentry);
ssize_t res;
int off;
const struct cred *old_cred;

old_cred = ovl_override_creds(dentry->d_sb);
res = vfs_listxattr(realdentry, list, size);
revert_creds(old_cred);
if (res <= 0 || size == 0)
return res;

Expand All @@ -295,6 +323,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
int err;
struct path realpath;
enum ovl_path_type type = ovl_path_real(dentry, &realpath);
const struct cred *old_cred;

err = ovl_want_write(dentry);
if (err)
Expand All @@ -316,7 +345,9 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
ovl_path_upper(dentry, &realpath);
}

old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_removexattr(realpath.dentry, name);
revert_creds(old_cred);
out_drop_write:
ovl_drop_write(dentry);
out:
Expand All @@ -326,14 +357,20 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
struct posix_acl *ovl_get_acl(struct inode *inode, int type)
{
struct inode *realinode = ovl_inode_real(inode);
const struct cred *old_cred;
struct posix_acl *acl;

if (!IS_POSIXACL(realinode))
return NULL;

if (!realinode->i_op->get_acl)
return NULL;

return realinode->i_op->get_acl(realinode, type);
old_cred = ovl_override_creds(inode->i_sb);
acl = realinode->i_op->get_acl(realinode, type);
revert_creds(old_cred);

return acl;
}

static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
Expand Down

0 comments on commit 1175b6b

Please sign in to comment.