Commit 09fc33ed authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Linus Torvalds

[PATCH] readlink in /proc w/ overlong path

Trying to read the overlong target of a /proc/*/fd/N file descriptor
leads to a SIGSEGV inside the kernel, because the code doesn't check
for an error pointer return from d_path.
parent 00a5bfb7
...@@ -565,10 +565,10 @@ static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) ...@@ -565,10 +565,10 @@ static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
} }
static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
char * buffer, int buflen) char *buffer, int buflen)
{ {
struct inode * inode; struct inode * inode;
char * tmp = (char*)__get_free_page(GFP_KERNEL), *path; char *tmp = (char*)__get_free_page(GFP_KERNEL), *path;
int len; int len;
if (!tmp) if (!tmp)
...@@ -576,13 +576,17 @@ static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, ...@@ -576,13 +576,17 @@ static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
inode = dentry->d_inode; inode = dentry->d_inode;
path = d_path(dentry, mnt, tmp, PAGE_SIZE); path = d_path(dentry, mnt, tmp, PAGE_SIZE);
len = PTR_ERR(path);
if (IS_ERR(path))
goto out;
len = tmp + PAGE_SIZE - 1 - path; len = tmp + PAGE_SIZE - 1 - path;
if (len < buflen) if (len > buflen)
buflen = len; len = buflen;
copy_to_user(buffer, path, buflen); copy_to_user(buffer, path, len);
out:
free_page((unsigned long)tmp); free_page((unsigned long)tmp);
return buflen; return len;
} }
static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen) static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment