Commit 1175b6b8 authored by Vivek Goyal's avatar Vivek Goyal Committed by Miklos Szeredi

ovl: do operations on underlying file system in mounter's context

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: default avatarVivek Goyal <vgoyal@redhat.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent c0ca3d70
...@@ -138,9 +138,12 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, ...@@ -138,9 +138,12 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
int err; int err;
enum ovl_path_type type; enum ovl_path_type type;
struct path realpath; struct path realpath;
const struct cred *old_cred;
type = ovl_path_real(dentry, &realpath); type = ovl_path_real(dentry, &realpath);
old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_getattr(&realpath, stat); err = vfs_getattr(&realpath, stat);
revert_creds(old_cred);
if (err) if (err)
return err; return err;
...@@ -391,6 +394,8 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev, ...@@ -391,6 +394,8 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
{ {
int err; int err;
struct inode *inode; struct inode *inode;
const struct cred *old_cred;
struct cred *override_cred;
struct kstat stat = { struct kstat stat = {
.mode = mode, .mode = mode,
.rdev = rdev, .rdev = rdev,
...@@ -405,28 +410,23 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev, ...@@ -405,28 +410,23 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
if (err) if (err)
goto out_iput; goto out_iput;
if (!ovl_dentry_is_opaque(dentry)) { old_cred = ovl_override_creds(dentry->d_sb);
err = ovl_create_upper(dentry, inode, &stat, link, hardlink); err = -ENOMEM;
} else { override_cred = prepare_creds();
const struct cred *old_cred; if (override_cred) {
struct cred *override_cred; override_cred->fsuid = old_cred->fsuid;
override_cred->fsgid = old_cred->fsgid;
old_cred = ovl_override_creds(dentry->d_sb); put_cred(override_creds(override_cred));
put_cred(override_cred);
err = -ENOMEM;
override_cred = prepare_creds(); if (!ovl_dentry_is_opaque(dentry))
if (override_cred) { err = ovl_create_upper(dentry, inode, &stat, link,
override_cred->fsuid = old_cred->fsuid; hardlink);
override_cred->fsgid = old_cred->fsgid; else
put_cred(override_creds(override_cred));
put_cred(override_cred);
err = ovl_create_over_whiteout(dentry, inode, &stat, err = ovl_create_over_whiteout(dentry, inode, &stat,
link, hardlink); link, hardlink);
}
revert_creds(old_cred);
} }
revert_creds(old_cred);
if (!err) if (!err)
inode = NULL; inode = NULL;
out_iput: out_iput:
...@@ -637,6 +637,8 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) ...@@ -637,6 +637,8 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
{ {
enum ovl_path_type type; enum ovl_path_type type;
int err; int err;
const struct cred *old_cred;
err = ovl_check_sticky(dentry); err = ovl_check_sticky(dentry);
if (err) if (err)
...@@ -651,15 +653,13 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) ...@@ -651,15 +653,13 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
goto out_drop_write; goto out_drop_write;
type = ovl_path_type(dentry); 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); err = ovl_remove_and_whiteout(dentry, is_dir);
revert_creds(old_cred);
revert_creds(old_cred);
}
out_drop_write: out_drop_write:
ovl_drop_write(dentry); ovl_drop_write(dentry);
out: out:
...@@ -764,8 +764,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, ...@@ -764,8 +764,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
old_opaque = !OVL_TYPE_PURE_UPPER(old_type); old_opaque = !OVL_TYPE_PURE_UPPER(old_type);
new_opaque = !OVL_TYPE_PURE_UPPER(new_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) { if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {
opaquedir = ovl_check_empty_and_clear(new); opaquedir = ovl_check_empty_and_clear(new);
...@@ -895,8 +894,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, ...@@ -895,8 +894,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
out_unlock: out_unlock:
unlock_rename(new_upperdir, old_upperdir); unlock_rename(new_upperdir, old_upperdir);
out_revert_creds: out_revert_creds:
if (old_opaque || new_opaque) revert_creds(old_cred);
revert_creds(old_cred);
out_drop_write: out_drop_write:
ovl_drop_write(old); ovl_drop_write(old);
out: out:
......
...@@ -41,6 +41,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -41,6 +41,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
{ {
int err; int err;
struct dentry *upperdentry; struct dentry *upperdentry;
const struct cred *old_cred;
/* /*
* Check for permissions before trying to copy-up. This is redundant * Check for permissions before trying to copy-up. This is redundant
...@@ -84,7 +85,9 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -84,7 +85,9 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
attr->ia_valid &= ~ATTR_MODE; attr->ia_valid &= ~ATTR_MODE;
inode_lock(upperdentry->d_inode); inode_lock(upperdentry->d_inode);
old_cred = ovl_override_creds(dentry->d_sb);
err = notify_change(upperdentry, attr, NULL); err = notify_change(upperdentry, attr, NULL);
revert_creds(old_cred);
if (!err) if (!err)
ovl_copyattr(upperdentry->d_inode, dentry->d_inode); ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
inode_unlock(upperdentry->d_inode); inode_unlock(upperdentry->d_inode);
...@@ -102,9 +105,14 @@ static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry, ...@@ -102,9 +105,14 @@ static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat) struct kstat *stat)
{ {
struct path realpath; struct path realpath;
const struct cred *old_cred;
int err;
ovl_path_real(dentry, &realpath); 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) int ovl_permission(struct inode *inode, int mask)
...@@ -188,6 +196,8 @@ static const char *ovl_get_link(struct dentry *dentry, ...@@ -188,6 +196,8 @@ static const char *ovl_get_link(struct dentry *dentry,
{ {
struct dentry *realdentry; struct dentry *realdentry;
struct inode *realinode; struct inode *realinode;
const struct cred *old_cred;
const char *p;
if (!dentry) if (!dentry)
return ERR_PTR(-ECHILD); return ERR_PTR(-ECHILD);
...@@ -198,13 +208,18 @@ static const char *ovl_get_link(struct dentry *dentry, ...@@ -198,13 +208,18 @@ static const char *ovl_get_link(struct dentry *dentry,
if (WARN_ON(!realinode->i_op->get_link)) if (WARN_ON(!realinode->i_op->get_link))
return ERR_PTR(-EPERM); 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) static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
{ {
struct path realpath; struct path realpath;
struct inode *realinode; struct inode *realinode;
const struct cred *old_cred;
int err;
ovl_path_real(dentry, &realpath); ovl_path_real(dentry, &realpath);
realinode = realpath.dentry->d_inode; realinode = realpath.dentry->d_inode;
...@@ -214,10 +229,12 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) ...@@ -214,10 +229,12 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
touch_atime(&realpath); 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) static bool ovl_is_private_xattr(const char *name)
{ {
return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0; return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0;
...@@ -229,6 +246,7 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode, ...@@ -229,6 +246,7 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode,
{ {
int err; int err;
struct dentry *upperdentry; struct dentry *upperdentry;
const struct cred *old_cred;
err = ovl_want_write(dentry); err = ovl_want_write(dentry);
if (err) if (err)
...@@ -243,7 +261,9 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode, ...@@ -243,7 +261,9 @@ int ovl_setxattr(struct dentry *dentry, struct inode *inode,
goto out_drop_write; goto out_drop_write;
upperdentry = ovl_dentry_upper(dentry); upperdentry = ovl_dentry_upper(dentry);
old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_setxattr(upperdentry, name, value, size, flags); err = vfs_setxattr(upperdentry, name, value, size, flags);
revert_creds(old_cred);
out_drop_write: out_drop_write:
ovl_drop_write(dentry); ovl_drop_write(dentry);
...@@ -255,11 +275,16 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, ...@@ -255,11 +275,16 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size) const char *name, void *value, size_t size)
{ {
struct dentry *realdentry = ovl_dentry_real(dentry); struct dentry *realdentry = ovl_dentry_real(dentry);
ssize_t res;
const struct cred *old_cred;
if (ovl_is_private_xattr(name)) if (ovl_is_private_xattr(name))
return -ENODATA; 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) ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
...@@ -267,8 +292,11 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) ...@@ -267,8 +292,11 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
struct dentry *realdentry = ovl_dentry_real(dentry); struct dentry *realdentry = ovl_dentry_real(dentry);
ssize_t res; ssize_t res;
int off; int off;
const struct cred *old_cred;
old_cred = ovl_override_creds(dentry->d_sb);
res = vfs_listxattr(realdentry, list, size); res = vfs_listxattr(realdentry, list, size);
revert_creds(old_cred);
if (res <= 0 || size == 0) if (res <= 0 || size == 0)
return res; return res;
...@@ -295,6 +323,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name) ...@@ -295,6 +323,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
int err; int err;
struct path realpath; struct path realpath;
enum ovl_path_type type = ovl_path_real(dentry, &realpath); enum ovl_path_type type = ovl_path_real(dentry, &realpath);
const struct cred *old_cred;
err = ovl_want_write(dentry); err = ovl_want_write(dentry);
if (err) if (err)
...@@ -316,7 +345,9 @@ int ovl_removexattr(struct dentry *dentry, const char *name) ...@@ -316,7 +345,9 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
ovl_path_upper(dentry, &realpath); ovl_path_upper(dentry, &realpath);
} }
old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_removexattr(realpath.dentry, name); err = vfs_removexattr(realpath.dentry, name);
revert_creds(old_cred);
out_drop_write: out_drop_write:
ovl_drop_write(dentry); ovl_drop_write(dentry);
out: out:
...@@ -326,6 +357,8 @@ int ovl_removexattr(struct dentry *dentry, const char *name) ...@@ -326,6 +357,8 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
struct posix_acl *ovl_get_acl(struct inode *inode, int type) struct posix_acl *ovl_get_acl(struct inode *inode, int type)
{ {
struct inode *realinode = ovl_inode_real(inode); struct inode *realinode = ovl_inode_real(inode);
const struct cred *old_cred;
struct posix_acl *acl;
if (!IS_POSIXACL(realinode)) if (!IS_POSIXACL(realinode))
return NULL; return NULL;
...@@ -333,7 +366,11 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type) ...@@ -333,7 +366,11 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type)
if (!realinode->i_op->get_acl) if (!realinode->i_op->get_acl)
return NULL; 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, static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
......
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