From 3f9ca75516a7e581ff803f751a869c1da5ae5fa5 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 9 Dec 2016 11:57:43 +0100 Subject: bad_inode: add missing i_op initializers New inode operations were forgotten to be added to bad_inode. Most of the time the op is checked for NULL before being called but marking the inode bad and the check can race (very unlikely). However in case of ->get_link() only DCACHE_SYMLINK_TYPE is checked before calling the op, so there's no race and will definitely oops when trying to follow links on such a beast. Also remove comments about extinct ops. Signed-off-by: Miklos Szeredi Cc: --- fs/bad_inode.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 8712062275b8..5f685c819298 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -106,6 +106,50 @@ static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer, return -EIO; } +static const char *bad_inode_get_link(struct dentry *dentry, + struct inode *inode, + struct delayed_call *done) +{ + return ERR_PTR(-EIO); +} + +static struct posix_acl *bad_inode_get_acl(struct inode *inode, int type) +{ + return ERR_PTR(-EIO); +} + +static int bad_inode_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo, u64 start, + u64 len) +{ + return -EIO; +} + +static int bad_inode_update_time(struct inode *inode, struct timespec *time, + int flags) +{ + return -EIO; +} + +static int bad_inode_atomic_open(struct inode *inode, struct dentry *dentry, + struct file *file, unsigned int open_flag, + umode_t create_mode, int *opened) +{ + return -EIO; +} + +static int bad_inode_tmpfile(struct inode *inode, struct dentry *dentry, + umode_t mode) +{ + return -EIO; +} + +static int bad_inode_set_acl(struct inode *inode, struct posix_acl *acl, + int type) +{ + return -EIO; +} + static const struct inode_operations bad_inode_ops = { .create = bad_inode_create, @@ -118,14 +162,17 @@ static const struct inode_operations bad_inode_ops = .mknod = bad_inode_mknod, .rename = bad_inode_rename2, .readlink = bad_inode_readlink, - /* follow_link must be no-op, otherwise unmounting this inode - won't work */ - /* put_link returns void */ - /* truncate returns void */ .permission = bad_inode_permission, .getattr = bad_inode_getattr, .setattr = bad_inode_setattr, .listxattr = bad_inode_listxattr, + .get_link = bad_inode_get_link, + .get_acl = bad_inode_get_acl, + .fiemap = bad_inode_fiemap, + .update_time = bad_inode_update_time, + .atomic_open = bad_inode_atomic_open, + .tmpfile = bad_inode_tmpfile, + .set_acl = bad_inode_set_acl, }; -- cgit v1.2.3-59-g8ed1b From 6c988f575915ab5162332d61f91dca99dcc17335 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 9 Dec 2016 16:45:03 +0100 Subject: ecryptfs: use vfs_get_link() Here again we are copying form one buffer to another, while jumping through hoops to make kernel memory look like userspace memory. For no good reason, since vfs_get_link() provides exactly what is needed. As a bonus, now the security hook for readlink is also called on the underlying inode. Note: this can be called from link-following context. But this is okay: - not in RCU mode - commit e54ad7f1ee26 ("proc: prevent stacking filesystems on top") - ecryptfs is *reading* the underlying symlink not following it, so the right security hook is being called Signed-off-by: Miklos Szeredi Cc: Tyler Hicks --- fs/ecryptfs/inode.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'fs') diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index cf390dceddd2..4ea9d69152dc 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -631,28 +631,23 @@ out_lock: static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz) { + DEFINE_DELAYED_CALL(done); struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - char *lower_buf; + const char *link; char *buf; - mm_segment_t old_fs; int rc; - lower_buf = kmalloc(PATH_MAX, GFP_KERNEL); - if (!lower_buf) - return ERR_PTR(-ENOMEM); - old_fs = get_fs(); - set_fs(get_ds()); - rc = d_inode(lower_dentry)->i_op->readlink(lower_dentry, - (char __user *)lower_buf, - PATH_MAX); - set_fs(old_fs); - if (rc < 0) - goto out; + link = vfs_get_link(lower_dentry, &done); + if (IS_ERR(link)) + return ERR_CAST(link); + rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb, - lower_buf, rc); -out: - kfree(lower_buf); - return rc ? ERR_PTR(rc) : buf; + link, strlen(link)); + do_delayed_call(&done); + if (rc) + return ERR_PTR(rc); + + return buf; } static const char *ecryptfs_get_link(struct dentry *dentry, -- cgit v1.2.3-59-g8ed1b From 2a07a1f5abba308729bd082dce4d035365165d85 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 9 Dec 2016 16:45:03 +0100 Subject: proc/self: use generic_readlink The /proc/self and /proc/self-thread symlinks have separate but identical functionality for reading and following. This cleanup utilizes generic_readlink to remove the duplication. Signed-off-by: Miklos Szeredi --- fs/proc/self.c | 14 +------------- fs/proc/thread_self.c | 15 +-------------- 2 files changed, 2 insertions(+), 27 deletions(-) (limited to 'fs') diff --git a/fs/proc/self.c b/fs/proc/self.c index 40245954c450..b7a29e55f802 100644 --- a/fs/proc/self.c +++ b/fs/proc/self.c @@ -6,18 +6,6 @@ /* * /proc/self: */ -static int proc_self_readlink(struct dentry *dentry, char __user *buffer, - int buflen) -{ - struct pid_namespace *ns = dentry->d_sb->s_fs_info; - pid_t tgid = task_tgid_nr_ns(current, ns); - char tmp[PROC_NUMBUF]; - if (!tgid) - return -ENOENT; - sprintf(tmp, "%d", tgid); - return readlink_copy(buffer, buflen, tmp); -} - static const char *proc_self_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) @@ -38,7 +26,7 @@ static const char *proc_self_get_link(struct dentry *dentry, } static const struct inode_operations proc_self_inode_operations = { - .readlink = proc_self_readlink, + .readlink = generic_readlink, .get_link = proc_self_get_link, }; diff --git a/fs/proc/thread_self.c b/fs/proc/thread_self.c index 595b90a9766c..adaba20b59b6 100644 --- a/fs/proc/thread_self.c +++ b/fs/proc/thread_self.c @@ -6,19 +6,6 @@ /* * /proc/thread_self: */ -static int proc_thread_self_readlink(struct dentry *dentry, char __user *buffer, - int buflen) -{ - struct pid_namespace *ns = dentry->d_sb->s_fs_info; - pid_t tgid = task_tgid_nr_ns(current, ns); - pid_t pid = task_pid_nr_ns(current, ns); - char tmp[PROC_NUMBUF + 6 + PROC_NUMBUF]; - if (!pid) - return -ENOENT; - sprintf(tmp, "%d/task/%d", tgid, pid); - return readlink_copy(buffer, buflen, tmp); -} - static const char *proc_thread_self_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) @@ -40,7 +27,7 @@ static const char *proc_thread_self_get_link(struct dentry *dentry, } static const struct inode_operations proc_thread_self_inode_operations = { - .readlink = proc_thread_self_readlink, + .readlink = generic_readlink, .get_link = proc_thread_self_get_link, }; -- cgit v1.2.3-59-g8ed1b From fd4a0edf2a3d781c6ae07d2810776ce22302ee1c Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 9 Dec 2016 16:45:04 +0100 Subject: vfs: replace calling i_op->readlink with vfs_readlink() Also check d_is_symlink() in callers instead of inode->i_op->readlink because following patches will allow NULL ->readlink for symlinks. Signed-off-by: Miklos Szeredi --- fs/namei.c | 21 +++++++++++++++++++++ fs/nfsd/nfs4xdr.c | 8 ++++---- fs/nfsd/vfs.c | 6 ++---- fs/stat.c | 8 +++++--- fs/xfs/xfs_ioctl.c | 4 ++-- include/linux/fs.h | 1 + 6 files changed, 35 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index 5b4eed221530..12a4159de72a 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4668,6 +4668,27 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) } EXPORT_SYMBOL(generic_readlink); +/** + * vfs_readlink - copy symlink body into userspace buffer + * @dentry: dentry on which to get symbolic link + * @buffer: user memory pointer + * @buflen: size of buffer + * + * Does not touch atime. That's up to the caller if necessary + * + * Does not call security hook. + */ +int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) +{ + struct inode *inode = d_inode(dentry); + + if (!inode->i_op->readlink) + return -EINVAL; + + return inode->i_op->readlink(dentry, buffer, buflen); +} +EXPORT_SYMBOL(vfs_readlink); + /** * vfs_get_link - get symlink body * @dentry: dentry on which to get symbolic link diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index c2d2895a1ec1..645e1e3c3110 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3576,10 +3576,10 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd if (!p) return nfserr_resource; /* - * XXX: By default, the ->readlink() VFS op will truncate symlinks - * if they would overflow the buffer. Is this kosher in NFSv4? If - * not, one easy fix is: if ->readlink() precisely fills the buffer, - * assume that truncation occurred, and return NFS4ERR_RESOURCE. + * XXX: By default, vfs_readlink() will truncate symlinks if they + * would overflow the buffer. Is this kosher in NFSv4? If not, one + * easy fix is: if vfs_readlink() precisely fills the buffer, assume + * that truncation occurred, and return NFS4ERR_RESOURCE. */ nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, (char *)p, &maxcount); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 8ca642fe9b21..b854f02c1c36 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1451,7 +1451,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, __be32 nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) { - struct inode *inode; mm_segment_t oldfs; __be32 err; int host_err; @@ -1463,10 +1462,9 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) path.mnt = fhp->fh_export->ex_path.mnt; path.dentry = fhp->fh_dentry; - inode = d_inode(path.dentry); err = nfserr_inval; - if (!inode->i_op->readlink) + if (!d_is_symlink(path.dentry)) goto out; touch_atime(&path); @@ -1475,7 +1473,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) */ oldfs = get_fs(); set_fs(KERNEL_DS); - host_err = inode->i_op->readlink(path.dentry, (char __user *)buf, *lenp); + host_err = vfs_readlink(path.dentry, (char __user *)buf, *lenp); set_fs(oldfs); if (host_err < 0) diff --git a/fs/stat.c b/fs/stat.c index bc045c7994e1..0b210c3ead5c 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -329,12 +329,14 @@ retry: struct inode *inode = d_backing_inode(path.dentry); error = empty ? -ENOENT : -EINVAL; - if (inode->i_op->readlink) { + /* + * AFS mountpoints allow readlink(2) but are not symlinks + */ + if (d_is_symlink(path.dentry) || inode->i_op->readlink) { error = security_inode_readlink(path.dentry); if (!error) { touch_atime(&path); - error = inode->i_op->readlink(path.dentry, - buf, bufsiz); + error = vfs_readlink(path.dentry, buf, bufsiz); } } path_put(&path); diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index c245bed3249b..9b12f7c993e9 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -287,7 +287,7 @@ xfs_readlink_by_handle( return PTR_ERR(dentry); /* Restrict this handle operation to symlinks only. */ - if (!d_inode(dentry)->i_op->readlink) { + if (!d_is_symlink(dentry)) { error = -EINVAL; goto out_dput; } @@ -297,7 +297,7 @@ xfs_readlink_by_handle( goto out_dput; } - error = d_inode(dentry)->i_op->readlink(dentry, hreq->ohandle, olen); + error = vfs_readlink(dentry, hreq->ohandle, olen); out_dput: dput(dentry); diff --git a/include/linux/fs.h b/include/linux/fs.h index dc0478c07b2a..eba20d1c068d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2935,6 +2935,7 @@ extern int vfs_lstat(const char __user *, struct kstat *); extern int vfs_fstat(unsigned int, struct kstat *); extern int vfs_fstatat(int , const char __user *, struct kstat *, int); extern const char *vfs_get_link(struct dentry *, struct delayed_call *); +extern int vfs_readlink(struct dentry *, char __user *, int); extern int __generic_block_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, -- cgit v1.2.3-59-g8ed1b From 76fca90e9f3abc82114d9d02d8e14e0324a18ca2 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 9 Dec 2016 16:45:04 +0100 Subject: vfs: default to generic_readlink() If i_op->readlink is NULL, but i_op->get_link is set then vfs_readlink() defaults to calling generic_readlink(). The IOP_DEFAULT_READLINK flag indicates that the above conditions are met and the default action can be taken. Signed-off-by: Miklos Szeredi --- Documentation/filesystems/porting | 4 ++++ Documentation/filesystems/vfs.txt | 9 ++++++--- fs/namei.c | 15 ++++++++++++--- include/linux/fs.h | 1 + 4 files changed, 23 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index bdd025ceb763..95280079c0b3 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -596,3 +596,7 @@ in your dentry operations instead. [mandatory] ->rename() has an added flags argument. Any flags not handled by the filesystem should result in EINVAL being returned. +-- +[recommended] + ->readlink is optional for symlinks. Don't set, unless filesystem needs + to fake something for readlink(2). diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index b5039a00caaf..038241123ca5 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -451,9 +451,6 @@ otherwise noted. exist; this is checked by the VFS. Unlike plain rename, source and target may be of different type. - readlink: called by the readlink(2) system call. Only required if - you want to support reading symbolic links - get_link: called by the VFS to follow a symbolic link to the inode it points to. Only required if you want to support symbolic links. This method returns the symlink body @@ -468,6 +465,12 @@ otherwise noted. argument. If request can't be handled without leaving RCU mode, have it return ERR_PTR(-ECHILD). + readlink: this is now just an override for use by readlink(2) for the + cases when ->get_link uses nd_jump_link() or object is not in + fact a symlink. Normally filesystems should only implement + ->get_link for symlinks and readlink(2) will automatically use + that. + permission: called by the VFS to check for access rights on a POSIX-like filesystem. diff --git a/fs/namei.c b/fs/namei.c index 12a4159de72a..b87465d67c60 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4682,10 +4682,19 @@ int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) { struct inode *inode = d_inode(dentry); - if (!inode->i_op->readlink) - return -EINVAL; + if (unlikely(!(inode->i_opflags & IOP_DEFAULT_READLINK))) { + if (unlikely(inode->i_op->readlink)) + return inode->i_op->readlink(dentry, buffer, buflen); + + if (!d_is_symlink(dentry)) + return -EINVAL; + + spin_lock(&inode->i_lock); + inode->i_opflags |= IOP_DEFAULT_READLINK; + spin_unlock(&inode->i_lock); + } - return inode->i_op->readlink(dentry, buffer, buflen); + return generic_readlink(dentry, buffer, buflen); } EXPORT_SYMBOL(vfs_readlink); diff --git a/include/linux/fs.h b/include/linux/fs.h index eba20d1c068d..f6c206eae6ac 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -595,6 +595,7 @@ is_uncached_acl(struct posix_acl *acl) #define IOP_LOOKUP 0x0002 #define IOP_NOFOLLOW 0x0004 #define IOP_XATTR 0x0008 +#define IOP_DEFAULT_READLINK 0x0010 /* * Keep mostly read-only and often accessed (especially for -- cgit v1.2.3-59-g8ed1b From dfeef68862edd7d4bafe68ef7aeb5f658ef24bb5 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 9 Dec 2016 16:45:04 +0100 Subject: vfs: remove ".readlink = generic_readlink" assignments If .readlink == NULL implies generic_readlink(). Generated by: to_del="\.readlink.*=.*generic_readlink" for i in `git grep -l $to_del`; do sed -i "/$to_del"/d $i; done Signed-off-by: Miklos Szeredi --- drivers/staging/lustre/lustre/llite/symlink.c | 1 - fs/9p/vfs_inode.c | 1 - fs/9p/vfs_inode_dotl.c | 1 - fs/affs/symlink.c | 1 - fs/autofs4/symlink.c | 1 - fs/btrfs/inode.c | 1 - fs/ceph/inode.c | 1 - fs/cifs/cifsfs.c | 1 - fs/coda/cnode.c | 1 - fs/configfs/symlink.c | 1 - fs/ecryptfs/inode.c | 1 - fs/ext2/symlink.c | 2 -- fs/ext4/symlink.c | 3 --- fs/f2fs/namei.c | 2 -- fs/fuse/dir.c | 1 - fs/gfs2/inode.c | 1 - fs/hostfs/hostfs_kern.c | 1 - fs/jffs2/symlink.c | 1 - fs/jfs/symlink.c | 2 -- fs/kernfs/symlink.c | 1 - fs/libfs.c | 1 - fs/minix/inode.c | 1 - fs/namei.c | 1 - fs/ncpfs/inode.c | 1 - fs/nfs/symlink.c | 1 - fs/nilfs2/namei.c | 1 - fs/ocfs2/symlink.c | 1 - fs/orangefs/symlink.c | 1 - fs/overlayfs/inode.c | 1 - fs/proc/inode.c | 1 - fs/proc/self.c | 1 - fs/proc/thread_self.c | 1 - fs/reiserfs/namei.c | 1 - fs/squashfs/symlink.c | 1 - fs/sysv/inode.c | 1 - fs/ubifs/file.c | 1 - fs/xfs/xfs_iops.c | 2 -- mm/shmem.c | 2 -- 38 files changed, 45 deletions(-) (limited to 'fs') diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c index 82c7c48aa619..cd77b55d3895 100644 --- a/drivers/staging/lustre/lustre/llite/symlink.c +++ b/drivers/staging/lustre/lustre/llite/symlink.c @@ -149,7 +149,6 @@ static const char *ll_get_link(struct dentry *dentry, } const struct inode_operations ll_fast_symlink_inode_operations = { - .readlink = generic_readlink, .setattr = ll_setattr, .get_link = ll_get_link, .getattr = ll_getattr, diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 30ca770c5e0b..f4f4450119e4 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1464,7 +1464,6 @@ static const struct inode_operations v9fs_file_inode_operations = { }; static const struct inode_operations v9fs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = v9fs_vfs_get_link, .getattr = v9fs_vfs_getattr, .setattr = v9fs_vfs_setattr, diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index afaa4b6de801..5999bd050678 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -979,7 +979,6 @@ const struct inode_operations v9fs_file_inode_operations_dotl = { }; const struct inode_operations v9fs_symlink_inode_operations_dotl = { - .readlink = generic_readlink, .get_link = v9fs_vfs_get_link_dotl, .getattr = v9fs_vfs_getattr_dotl, .setattr = v9fs_vfs_setattr_dotl, diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index 69b03dbb792f..ae622cdce142 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -70,7 +70,6 @@ const struct address_space_operations affs_symlink_aops = { }; const struct inode_operations affs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .setattr = affs_notify_change, }; diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index 99aab00dc217..ab0b4285a202 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c @@ -25,6 +25,5 @@ static const char *autofs4_get_link(struct dentry *dentry, } const struct inode_operations autofs4_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = autofs4_get_link }; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8e3a5a266917..d9c0eb7c16d4 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -10668,7 +10668,6 @@ static const struct inode_operations btrfs_special_inode_operations = { .update_time = btrfs_update_time, }; static const struct inode_operations btrfs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .getattr = btrfs_getattr, .setattr = btrfs_setattr, diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index ef4d04647325..9f125204c487 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1879,7 +1879,6 @@ retry: * symlinks */ static const struct inode_operations ceph_symlink_iops = { - .readlink = generic_readlink, .get_link = simple_get_link, .setattr = ceph_setattr, .getattr = ceph_getattr, diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 15261ba464c5..e6efb9a88598 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -914,7 +914,6 @@ const struct inode_operations cifs_file_inode_ops = { }; const struct inode_operations cifs_symlink_inode_ops = { - .readlink = generic_readlink, .get_link = cifs_get_link, .permission = cifs_permission, .listxattr = cifs_listxattr, diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 1bfb7ba4e85e..f13e09057c6b 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -17,7 +17,6 @@ static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) } static const struct inode_operations coda_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .setattr = coda_setattr, }; diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index db6d69289608..a6ab012a2c6a 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -305,7 +305,6 @@ static const char *configfs_get_link(struct dentry *dentry, const struct inode_operations configfs_symlink_inode_operations = { .get_link = configfs_get_link, - .readlink = generic_readlink, .setattr = configfs_setattr, }; diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 4ea9d69152dc..e7413f82d27b 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -1084,7 +1084,6 @@ out: } const struct inode_operations ecryptfs_symlink_iops = { - .readlink = generic_readlink, .get_link = ecryptfs_get_link, .permission = ecryptfs_permission, .setattr = ecryptfs_setattr, diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index 8437b191bf5d..eeffb0138a17 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -21,7 +21,6 @@ #include "xattr.h" const struct inode_operations ext2_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .setattr = ext2_setattr, #ifdef CONFIG_EXT2_FS_XATTR @@ -30,7 +29,6 @@ const struct inode_operations ext2_symlink_inode_operations = { }; const struct inode_operations ext2_fast_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = simple_get_link, .setattr = ext2_setattr, #ifdef CONFIG_EXT2_FS_XATTR diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index 557b3b0d668c..73b184d161fc 100644 --- a/fs/ext4/symlink.c +++ b/fs/ext4/symlink.c @@ -83,21 +83,18 @@ errout: } const struct inode_operations ext4_encrypted_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = ext4_encrypted_get_link, .setattr = ext4_setattr, .listxattr = ext4_listxattr, }; const struct inode_operations ext4_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .setattr = ext4_setattr, .listxattr = ext4_listxattr, }; const struct inode_operations ext4_fast_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = simple_get_link, .setattr = ext4_setattr, .listxattr = ext4_listxattr, diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 489fa0d5f914..fcb00e7c3054 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -1075,7 +1075,6 @@ errout: } const struct inode_operations f2fs_encrypted_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = f2fs_encrypted_get_link, .getattr = f2fs_getattr, .setattr = f2fs_setattr, @@ -1105,7 +1104,6 @@ const struct inode_operations f2fs_dir_inode_operations = { }; const struct inode_operations f2fs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = f2fs_get_link, .getattr = f2fs_getattr, .setattr = f2fs_setattr, diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index b3ebe512d64c..0c07d0c651de 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1834,7 +1834,6 @@ static const struct inode_operations fuse_common_inode_operations = { static const struct inode_operations fuse_symlink_inode_operations = { .setattr = fuse_setattr, .get_link = fuse_get_link, - .readlink = generic_readlink, .getattr = fuse_getattr, .listxattr = fuse_listxattr, }; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index fe3f84995c48..6cd9f84967b8 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -2067,7 +2067,6 @@ const struct inode_operations gfs2_dir_iops = { }; const struct inode_operations gfs2_symlink_iops = { - .readlink = generic_readlink, .get_link = gfs2_get_link, .permission = gfs2_permission, .setattr = gfs2_setattr, diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 23e15ea53e45..e61261a7417e 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -920,7 +920,6 @@ static const char *hostfs_get_link(struct dentry *dentry, } static const struct inode_operations hostfs_link_iops = { - .readlink = generic_readlink, .get_link = hostfs_get_link, }; diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 8f3f0855fcd2..d2fa138a868c 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -13,7 +13,6 @@ const struct inode_operations jffs2_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = simple_get_link, .setattr = jffs2_setattr, .listxattr = jffs2_listxattr, diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c index c82404fee6cd..38320607993e 100644 --- a/fs/jfs/symlink.c +++ b/fs/jfs/symlink.c @@ -22,14 +22,12 @@ #include "jfs_xattr.h" const struct inode_operations jfs_fast_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = simple_get_link, .setattr = jfs_setattr, .listxattr = jfs_listxattr, }; const struct inode_operations jfs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .setattr = jfs_setattr, .listxattr = jfs_listxattr, diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 9b43ca02b7ab..1684af4a8b9b 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -135,7 +135,6 @@ static const char *kernfs_iop_get_link(struct dentry *dentry, const struct inode_operations kernfs_symlink_iops = { .listxattr = kernfs_iop_listxattr, - .readlink = generic_readlink, .get_link = kernfs_iop_get_link, .setattr = kernfs_iop_setattr, .getattr = kernfs_iop_getattr, diff --git a/fs/libfs.c b/fs/libfs.c index 48826d4da189..06e7e0c918e1 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -1129,7 +1129,6 @@ EXPORT_SYMBOL(simple_get_link); const struct inode_operations simple_symlink_inode_operations = { .get_link = simple_get_link, - .readlink = generic_readlink }; EXPORT_SYMBOL(simple_symlink_inode_operations); diff --git a/fs/minix/inode.c b/fs/minix/inode.c index f975d667c539..e7d9bf86d975 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -434,7 +434,6 @@ static const struct address_space_operations minix_aops = { }; static const struct inode_operations minix_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .getattr = minix_getattr, }; diff --git a/fs/namei.c b/fs/namei.c index b87465d67c60..c9baf3b3ffd7 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4813,7 +4813,6 @@ int page_symlink(struct inode *inode, const char *symname, int len) EXPORT_SYMBOL(page_symlink); const struct inode_operations page_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, }; EXPORT_SYMBOL(page_symlink_inode_operations); diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index f6cf4c7e92b1..ba611bf1aff3 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -243,7 +243,6 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) static const struct inode_operations ncp_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .setattr = ncp_notify_change, }; diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 4fe3eead3868..5a1d0ded8979 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -77,7 +77,6 @@ static const char *nfs_get_link(struct dentry *dentry, * symlinks can't do much... */ const struct inode_operations nfs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = nfs_get_link, .getattr = nfs_getattr, .setattr = nfs_setattr, diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 2b71c60fe982..515d13c196da 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -568,7 +568,6 @@ const struct inode_operations nilfs_special_inode_operations = { }; const struct inode_operations nilfs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .permission = nilfs_permission, }; diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 6ad8eecefe21..94cfacc9bad7 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -87,7 +87,6 @@ const struct address_space_operations ocfs2_fast_symlink_aops = { }; const struct inode_operations ocfs2_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .getattr = ocfs2_getattr, .setattr = ocfs2_setattr, diff --git a/fs/orangefs/symlink.c b/fs/orangefs/symlink.c index 10b0b06e075e..02b1bbdbcc42 100644 --- a/fs/orangefs/symlink.c +++ b/fs/orangefs/symlink.c @@ -9,7 +9,6 @@ #include "orangefs-bufmap.h" const struct inode_operations orangefs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = simple_get_link, .setattr = orangefs_setattr, .getattr = orangefs_getattr, diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 7fb53d055537..19e0089c3dbf 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -348,7 +348,6 @@ static const struct inode_operations ovl_file_inode_operations = { static const struct inode_operations ovl_symlink_inode_operations = { .setattr = ovl_setattr, .get_link = ovl_get_link, - .readlink = generic_readlink, .getattr = ovl_getattr, .listxattr = ovl_listxattr, .update_time = ovl_update_time, diff --git a/fs/proc/inode.c b/fs/proc/inode.c index e69ebe648a34..827c0df5baa6 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -410,7 +410,6 @@ static const char *proc_get_link(struct dentry *dentry, } const struct inode_operations proc_link_inode_operations = { - .readlink = generic_readlink, .get_link = proc_get_link, }; diff --git a/fs/proc/self.c b/fs/proc/self.c index b7a29e55f802..39857f6db5cf 100644 --- a/fs/proc/self.c +++ b/fs/proc/self.c @@ -26,7 +26,6 @@ static const char *proc_self_get_link(struct dentry *dentry, } static const struct inode_operations proc_self_inode_operations = { - .readlink = generic_readlink, .get_link = proc_self_get_link, }; diff --git a/fs/proc/thread_self.c b/fs/proc/thread_self.c index adaba20b59b6..20614b62a9b7 100644 --- a/fs/proc/thread_self.c +++ b/fs/proc/thread_self.c @@ -27,7 +27,6 @@ static const char *proc_thread_self_get_link(struct dentry *dentry, } static const struct inode_operations proc_thread_self_inode_operations = { - .readlink = generic_readlink, .get_link = proc_thread_self_get_link, }; diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index e6a2b406af36..bd39a998843d 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -1665,7 +1665,6 @@ const struct inode_operations reiserfs_dir_inode_operations = { * stuff added */ const struct inode_operations reiserfs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .setattr = reiserfs_setattr, .listxattr = reiserfs_listxattr, diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c index 79b9c31a0c8f..befeba0fa70a 100644 --- a/fs/squashfs/symlink.c +++ b/fs/squashfs/symlink.c @@ -118,7 +118,6 @@ const struct address_space_operations squashfs_symlink_aops = { }; const struct inode_operations squashfs_symlink_inode_ops = { - .readlink = generic_readlink, .get_link = page_get_link, .listxattr = squashfs_listxattr }; diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index d62c423a5a2d..858fb72f9e0f 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -145,7 +145,6 @@ static inline void write3byte(struct sysv_sb_info *sbi, } static const struct inode_operations sysv_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .getattr = sysv_getattr, }; diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index b4fbeefba246..a7eae181e1bd 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -1628,7 +1628,6 @@ const struct inode_operations ubifs_file_inode_operations = { }; const struct inode_operations ubifs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = simple_get_link, .setattr = ubifs_setattr, .getattr = ubifs_getattr, diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 405a65cd9d6b..de79f29c7e5b 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1122,7 +1122,6 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { }; static const struct inode_operations xfs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = xfs_vn_get_link, .getattr = xfs_vn_getattr, .setattr = xfs_vn_setattr, @@ -1131,7 +1130,6 @@ static const struct inode_operations xfs_symlink_inode_operations = { }; static const struct inode_operations xfs_inline_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = xfs_vn_get_link_inline, .getattr = xfs_vn_getattr, .setattr = xfs_vn_setattr, diff --git a/mm/shmem.c b/mm/shmem.c index 166ebf5d2bce..aa47e6baecde 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3174,7 +3174,6 @@ static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size) #endif /* CONFIG_TMPFS_XATTR */ static const struct inode_operations shmem_short_symlink_operations = { - .readlink = generic_readlink, .get_link = simple_get_link, #ifdef CONFIG_TMPFS_XATTR .listxattr = shmem_listxattr, @@ -3182,7 +3181,6 @@ static const struct inode_operations shmem_short_symlink_operations = { }; static const struct inode_operations shmem_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = shmem_get_link, #ifdef CONFIG_TMPFS_XATTR .listxattr = shmem_listxattr, -- cgit v1.2.3-59-g8ed1b From d16744ec8ad011793144bb932ce822cc0c1733cb Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 9 Dec 2016 16:45:04 +0100 Subject: vfs: make generic_readlink() static Signed-off-by: Miklos Szeredi --- fs/namei.c | 4 ++-- include/linux/fs.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index c9baf3b3ffd7..c248a9e1edd2 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4650,7 +4650,8 @@ out: * have ->get_link() not calling nd_jump_link(). Using (or not using) it * for any given inode is up to filesystem. */ -int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) +static int generic_readlink(struct dentry *dentry, char __user *buffer, + int buflen) { DEFINE_DELAYED_CALL(done); struct inode *inode = d_inode(dentry); @@ -4666,7 +4667,6 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) do_delayed_call(&done); return res; } -EXPORT_SYMBOL(generic_readlink); /** * vfs_readlink - copy symlink body into userspace buffer diff --git a/include/linux/fs.h b/include/linux/fs.h index f6c206eae6ac..e343d784651a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2915,7 +2915,6 @@ extern int __page_symlink(struct inode *inode, const char *symname, int len, extern int page_symlink(struct inode *inode, const char *symname, int len); extern const struct inode_operations page_symlink_inode_operations; extern void kfree_link(void *); -extern int generic_readlink(struct dentry *, char __user *, int); extern void generic_fillattr(struct inode *, struct kstat *); int vfs_getattr_nosec(struct path *path, struct kstat *stat); extern int vfs_getattr(struct path *, struct kstat *); -- cgit v1.2.3-59-g8ed1b