ovl: use vfs_get_link()
Resulting in a complete removal of a function basically implementing the inverse of vfs_readlink(). As a bonus, now the proper security hook is also called. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
d60874cd58
commit
7764235bec
|
@ -177,40 +177,6 @@ out_fput:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ovl_read_symlink(struct dentry *realdentry)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
char *buf;
|
|
||||||
struct inode *inode = realdentry->d_inode;
|
|
||||||
mm_segment_t old_fs;
|
|
||||||
|
|
||||||
res = -EINVAL;
|
|
||||||
if (!inode->i_op->readlink)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
res = -ENOMEM;
|
|
||||||
buf = (char *) __get_free_page(GFP_KERNEL);
|
|
||||||
if (!buf)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
old_fs = get_fs();
|
|
||||||
set_fs(get_ds());
|
|
||||||
/* The cast to a user pointer is valid due to the set_fs() */
|
|
||||||
res = inode->i_op->readlink(realdentry,
|
|
||||||
(char __user *)buf, PAGE_SIZE - 1);
|
|
||||||
set_fs(old_fs);
|
|
||||||
if (res < 0) {
|
|
||||||
free_page((unsigned long) buf);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
buf[res] = '\0';
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
|
|
||||||
err:
|
|
||||||
return ERR_PTR(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat)
|
static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat)
|
||||||
{
|
{
|
||||||
struct iattr attr = {
|
struct iattr attr = {
|
||||||
|
@ -342,18 +308,20 @@ out_cleanup:
|
||||||
int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
|
int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
|
||||||
struct path *lowerpath, struct kstat *stat)
|
struct path *lowerpath, struct kstat *stat)
|
||||||
{
|
{
|
||||||
|
DEFINE_DELAYED_CALL(done);
|
||||||
struct dentry *workdir = ovl_workdir(dentry);
|
struct dentry *workdir = ovl_workdir(dentry);
|
||||||
int err;
|
int err;
|
||||||
struct kstat pstat;
|
struct kstat pstat;
|
||||||
struct path parentpath;
|
struct path parentpath;
|
||||||
|
struct dentry *lowerdentry = lowerpath->dentry;
|
||||||
struct dentry *upperdir;
|
struct dentry *upperdir;
|
||||||
struct dentry *upperdentry;
|
struct dentry *upperdentry;
|
||||||
char *link = NULL;
|
const char *link = NULL;
|
||||||
|
|
||||||
if (WARN_ON(!workdir))
|
if (WARN_ON(!workdir))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
ovl_do_check_copy_up(lowerpath->dentry);
|
ovl_do_check_copy_up(lowerdentry);
|
||||||
|
|
||||||
ovl_path_upper(parent, &parentpath);
|
ovl_path_upper(parent, &parentpath);
|
||||||
upperdir = parentpath.dentry;
|
upperdir = parentpath.dentry;
|
||||||
|
@ -363,7 +331,7 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (S_ISLNK(stat->mode)) {
|
if (S_ISLNK(stat->mode)) {
|
||||||
link = ovl_read_symlink(lowerpath->dentry);
|
link = vfs_get_link(lowerdentry, &done);
|
||||||
if (IS_ERR(link))
|
if (IS_ERR(link))
|
||||||
return PTR_ERR(link);
|
return PTR_ERR(link);
|
||||||
}
|
}
|
||||||
|
@ -388,9 +356,7 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
|
||||||
}
|
}
|
||||||
out_unlock:
|
out_unlock:
|
||||||
unlock_rename(workdir, upperdir);
|
unlock_rename(workdir, upperdir);
|
||||||
|
do_delayed_call(&done);
|
||||||
if (link)
|
|
||||||
free_page((unsigned long) link);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,22 +156,14 @@ static const char *ovl_get_link(struct dentry *dentry,
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
struct delayed_call *done)
|
struct delayed_call *done)
|
||||||
{
|
{
|
||||||
struct dentry *realdentry;
|
|
||||||
struct inode *realinode;
|
|
||||||
const struct cred *old_cred;
|
const struct cred *old_cred;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
if (!dentry)
|
if (!dentry)
|
||||||
return ERR_PTR(-ECHILD);
|
return ERR_PTR(-ECHILD);
|
||||||
|
|
||||||
realdentry = ovl_dentry_real(dentry);
|
|
||||||
realinode = realdentry->d_inode;
|
|
||||||
|
|
||||||
if (WARN_ON(!realinode->i_op->get_link))
|
|
||||||
return ERR_PTR(-EPERM);
|
|
||||||
|
|
||||||
old_cred = ovl_override_creds(dentry->d_sb);
|
old_cred = ovl_override_creds(dentry->d_sb);
|
||||||
p = realinode->i_op->get_link(realdentry, realinode, done);
|
p = vfs_get_link(ovl_dentry_real(dentry), done);
|
||||||
revert_creds(old_cred);
|
revert_creds(old_cred);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue