[PATCH 16/17] ovl: use vfs_get_link()

From: Miklos Szeredi
Date: Mon Sep 12 2016 - 15:30:54 EST


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@xxxxxxxxxx>
---
fs/overlayfs/copy_up.c | 45 ++++++---------------------------------------
fs/overlayfs/inode.c | 5 +----
2 files changed, 7 insertions(+), 43 deletions(-)

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index a2d4c10dd74d..c3371d62d931 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -167,39 +167,6 @@ out_fput:
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->get_link)
- 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 = vfs_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)
{
struct iattr attr = {
@@ -331,19 +298,21 @@ out_cleanup:
int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
struct path *lowerpath, struct kstat *stat)
{
+ DEFINE_DELAYED_CALL(done);
struct dentry *workdir = ovl_workdir(dentry);
int err;
struct kstat pstat;
struct path parentpath;
+ struct dentry *lowerdentry = lowerpath->dentry;
struct dentry *upperdir;
struct dentry *upperdentry;
const struct cred *old_cred;
- char *link = NULL;
+ const char *link = NULL;

if (WARN_ON(!workdir))
return -EROFS;

- ovl_do_check_copy_up(lowerpath->dentry);
+ ovl_do_check_copy_up(lowerdentry);

ovl_path_upper(parent, &parentpath);
upperdir = parentpath.dentry;
@@ -353,7 +322,7 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
return err;

if (S_ISLNK(stat->mode)) {
- link = ovl_read_symlink(lowerpath->dentry);
+ link = vfs_get_link(lowerdentry, d_inode(lowerdentry), &done);
if (IS_ERR(link))
return PTR_ERR(link);
}
@@ -381,9 +350,7 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
out_unlock:
unlock_rename(workdir, upperdir);
revert_creds(old_cred);
-
- if (link)
- free_page((unsigned long) link);
+ do_delayed_call(&done);

return err;
}
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index db8975f59021..6be9bb470fd9 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -164,11 +164,8 @@ static const char *ovl_get_link(struct dentry *dentry,
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);
- p = realinode->i_op->get_link(realdentry, realinode, done);
+ p = vfs_get_link(realdentry, realinode, done);
revert_creds(old_cred);
return p;
}
--
2.5.5