aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namei.c13
-rw-r--r--fs/proc/namespaces.c14
-rw-r--r--fs/proc/self.c2
-rw-r--r--fs/xfs/xfs_ioctl.c28
-rw-r--r--include/linux/fs.h2
5 files changed, 12 insertions, 47 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 617de9e9967b..4fb52f0ca5cb 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4297,11 +4297,9 @@ SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newna
4297 return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname); 4297 return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname);
4298} 4298}
4299 4299
4300int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) 4300int readlink_copy(char __user *buffer, int buflen, const char *link)
4301{ 4301{
4302 int len; 4302 int len = PTR_ERR(link);
4303
4304 len = PTR_ERR(link);
4305 if (IS_ERR(link)) 4303 if (IS_ERR(link))
4306 goto out; 4304 goto out;
4307 4305
@@ -4313,7 +4311,7 @@ int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const c
4313out: 4311out:
4314 return len; 4312 return len;
4315} 4313}
4316EXPORT_SYMBOL(vfs_readlink); 4314EXPORT_SYMBOL(readlink_copy);
4317 4315
4318/* 4316/*
4319 * A helper for ->readlink(). This should be used *ONLY* for symlinks that 4317 * A helper for ->readlink(). This should be used *ONLY* for symlinks that
@@ -4331,7 +4329,7 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
4331 if (IS_ERR(cookie)) 4329 if (IS_ERR(cookie))
4332 return PTR_ERR(cookie); 4330 return PTR_ERR(cookie);
4333 4331
4334 res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); 4332 res = readlink_copy(buffer, buflen, nd_get_link(&nd));
4335 if (dentry->d_inode->i_op->put_link) 4333 if (dentry->d_inode->i_op->put_link)
4336 dentry->d_inode->i_op->put_link(dentry, &nd, cookie); 4334 dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
4337 return res; 4335 return res;
@@ -4356,8 +4354,7 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage)
4356int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) 4354int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
4357{ 4355{
4358 struct page *page = NULL; 4356 struct page *page = NULL;
4359 char *s = page_getlink(dentry, &page); 4357 int res = readlink_copy(buffer, buflen, page_getlink(dentry, &page));
4360 int res = vfs_readlink(dentry,buffer,buflen,s);
4361 if (page) { 4358 if (page) {
4362 kunmap(page); 4359 kunmap(page);
4363 page_cache_release(page); 4360 page_cache_release(page);
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 9ae46b87470d..89026095f2b5 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -146,7 +146,7 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl
146 struct task_struct *task; 146 struct task_struct *task;
147 void *ns; 147 void *ns;
148 char name[50]; 148 char name[50];
149 int len = -EACCES; 149 int res = -EACCES;
150 150
151 task = get_proc_task(inode); 151 task = get_proc_task(inode);
152 if (!task) 152 if (!task)
@@ -155,24 +155,18 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl
155 if (!ptrace_may_access(task, PTRACE_MODE_READ)) 155 if (!ptrace_may_access(task, PTRACE_MODE_READ))
156 goto out_put_task; 156 goto out_put_task;
157 157
158 len = -ENOENT; 158 res = -ENOENT;
159 ns = ns_ops->get(task); 159 ns = ns_ops->get(task);
160 if (!ns) 160 if (!ns)
161 goto out_put_task; 161 goto out_put_task;
162 162
163 snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns)); 163 snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
164 len = strlen(name); 164 res = readlink_copy(buffer, buflen, name);
165
166 if (len > buflen)
167 len = buflen;
168 if (copy_to_user(buffer, name, len))
169 len = -EFAULT;
170
171 ns_ops->put(ns); 165 ns_ops->put(ns);
172out_put_task: 166out_put_task:
173 put_task_struct(task); 167 put_task_struct(task);
174out: 168out:
175 return len; 169 return res;
176} 170}
177 171
178static const struct inode_operations proc_ns_link_inode_operations = { 172static const struct inode_operations proc_ns_link_inode_operations = {
diff --git a/fs/proc/self.c b/fs/proc/self.c
index ffeb202ec942..4348bb8907c2 100644
--- a/fs/proc/self.c
+++ b/fs/proc/self.c
@@ -16,7 +16,7 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
16 if (!tgid) 16 if (!tgid)
17 return -ENOENT; 17 return -ENOENT;
18 sprintf(tmp, "%d", tgid); 18 sprintf(tmp, "%d", tgid);
19 return vfs_readlink(dentry,buffer,buflen,tmp); 19 return readlink_copy(buffer, buflen, tmp);
20} 20}
21 21
22static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) 22static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index bcfe61202115..0b18776b075e 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -271,32 +271,6 @@ xfs_open_by_handle(
271 return error; 271 return error;
272} 272}
273 273
274/*
275 * This is a copy from fs/namei.c:vfs_readlink(), except for removing it's
276 * unused first argument.
277 */
278STATIC int
279do_readlink(
280 char __user *buffer,
281 int buflen,
282 const char *link)
283{
284 int len;
285
286 len = PTR_ERR(link);
287 if (IS_ERR(link))
288 goto out;
289
290 len = strlen(link);
291 if (len > (unsigned) buflen)
292 len = buflen;
293 if (copy_to_user(buffer, link, len))
294 len = -EFAULT;
295 out:
296 return len;
297}
298
299
300int 274int
301xfs_readlink_by_handle( 275xfs_readlink_by_handle(
302 struct file *parfilp, 276 struct file *parfilp,
@@ -334,7 +308,7 @@ xfs_readlink_by_handle(
334 error = -xfs_readlink(XFS_I(dentry->d_inode), link); 308 error = -xfs_readlink(XFS_I(dentry->d_inode), link);
335 if (error) 309 if (error)
336 goto out_kfree; 310 goto out_kfree;
337 error = do_readlink(hreq->ohandle, olen, link); 311 error = readlink_copy(hreq->ohandle, olen, link);
338 if (error) 312 if (error)
339 goto out_kfree; 313 goto out_kfree;
340 314
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d9d88a0b456e..db181b542db1 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2517,7 +2517,7 @@ extern const struct file_operations generic_ro_fops;
2517 2517
2518#define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) 2518#define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
2519 2519
2520extern int vfs_readlink(struct dentry *, char __user *, int, const char *); 2520extern int readlink_copy(char __user *, int, const char *);
2521extern int page_readlink(struct dentry *, char __user *, int); 2521extern int page_readlink(struct dentry *, char __user *, int);
2522extern void *page_follow_link_light(struct dentry *, struct nameidata *); 2522extern void *page_follow_link_light(struct dentry *, struct nameidata *);
2523extern void page_put_link(struct dentry *, struct nameidata *, void *); 2523extern void page_put_link(struct dentry *, struct nameidata *, void *);