aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2016-10-04 08:40:45 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2016-10-14 05:16:47 -0400
commitd60874cd58fcb21372f2df698c20f8cf2f78fdcb (patch)
treeeade1cfdc44321b875a51d1beef4042e9e657165
parent78a3fa4f3249055b472983065b30c02392cf7e2a (diff)
vfs: add vfs_get_link() helper
This helper is for filesystems that want to read the symlink and are better off with the get_link() interface (returning a char *) rather than the readlink() interface (copy into a userspace buffer). Also call the LSM hook for readlink (not get_link) since this is for symlink reading not following. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/namei.c25
-rw-r--r--include/linux/fs.h1
2 files changed, 26 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index adb04146df09..8a2c2959da08 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4677,6 +4677,31 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
4677} 4677}
4678EXPORT_SYMBOL(generic_readlink); 4678EXPORT_SYMBOL(generic_readlink);
4679 4679
4680/**
4681 * vfs_get_link - get symlink body
4682 * @dentry: dentry on which to get symbolic link
4683 * @done: caller needs to free returned data with this
4684 *
4685 * Calls security hook and i_op->get_link() on the supplied inode.
4686 *
4687 * It does not touch atime. That's up to the caller if necessary.
4688 *
4689 * Does not work on "special" symlinks like /proc/$$/fd/N
4690 */
4691const char *vfs_get_link(struct dentry *dentry, struct delayed_call *done)
4692{
4693 const char *res = ERR_PTR(-EINVAL);
4694 struct inode *inode = d_inode(dentry);
4695
4696 if (d_is_symlink(dentry)) {
4697 res = ERR_PTR(security_inode_readlink(dentry));
4698 if (!res)
4699 res = inode->i_op->get_link(dentry, inode, done);
4700 }
4701 return res;
4702}
4703EXPORT_SYMBOL(vfs_get_link);
4704
4680/* get the link contents into pagecache */ 4705/* get the link contents into pagecache */
4681const char *page_get_link(struct dentry *dentry, struct inode *inode, 4706const char *page_get_link(struct dentry *dentry, struct inode *inode,
4682 struct delayed_call *callback) 4707 struct delayed_call *callback)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 901e25d495cc..bc8ac5108368 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2919,6 +2919,7 @@ extern int vfs_stat(const char __user *, struct kstat *);
2919extern int vfs_lstat(const char __user *, struct kstat *); 2919extern int vfs_lstat(const char __user *, struct kstat *);
2920extern int vfs_fstat(unsigned int, struct kstat *); 2920extern int vfs_fstat(unsigned int, struct kstat *);
2921extern int vfs_fstatat(int , const char __user *, struct kstat *, int); 2921extern int vfs_fstatat(int , const char __user *, struct kstat *, int);
2922extern const char *vfs_get_link(struct dentry *, struct delayed_call *);
2922 2923
2923extern int __generic_block_fiemap(struct inode *inode, 2924extern int __generic_block_fiemap(struct inode *inode,
2924 struct fiemap_extent_info *fieinfo, 2925 struct fiemap_extent_info *fieinfo,