diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2016-10-04 08:40:45 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-10-14 05:16:47 -0400 |
commit | d60874cd58fcb21372f2df698c20f8cf2f78fdcb (patch) | |
tree | eade1cfdc44321b875a51d1beef4042e9e657165 | |
parent | 78a3fa4f3249055b472983065b30c02392cf7e2a (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.c | 25 | ||||
-rw-r--r-- | include/linux/fs.h | 1 |
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 | } |
4678 | EXPORT_SYMBOL(generic_readlink); | 4678 | EXPORT_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 | */ | ||
4691 | const 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 | } | ||
4703 | EXPORT_SYMBOL(vfs_get_link); | ||
4704 | |||
4680 | /* get the link contents into pagecache */ | 4705 | /* get the link contents into pagecache */ |
4681 | const char *page_get_link(struct dentry *dentry, struct inode *inode, | 4706 | const 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 *); | |||
2919 | extern int vfs_lstat(const char __user *, struct kstat *); | 2919 | extern int vfs_lstat(const char __user *, struct kstat *); |
2920 | extern int vfs_fstat(unsigned int, struct kstat *); | 2920 | extern int vfs_fstat(unsigned int, struct kstat *); |
2921 | extern int vfs_fstatat(int , const char __user *, struct kstat *, int); | 2921 | extern int vfs_fstatat(int , const char __user *, struct kstat *, int); |
2922 | extern const char *vfs_get_link(struct dentry *, struct delayed_call *); | ||
2922 | 2923 | ||
2923 | extern int __generic_block_fiemap(struct inode *inode, | 2924 | extern int __generic_block_fiemap(struct inode *inode, |
2924 | struct fiemap_extent_info *fieinfo, | 2925 | struct fiemap_extent_info *fieinfo, |