| From stable-bounces@linux.kernel.org Fri Dec 30 22:13:50 2005 |
| Date: Fri, 30 Dec 2005 09:59:56 -0800 |
| Message-Id: <200512301759.jBUHxuXV001610@hera.kernel.org> |
| From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org> |
| To: git-commits-head@vger.kernel.org |
| Cc: |
| Subject: Insanity avoidance in /proc (CVE-2005-4605) |
| |
| From: Linus Torvalds <torvalds@osdl.org> |
| |
| Insanity avoidance in /proc |
| |
| The old /proc interfaces were never updated to use loff_t, and are just |
| generally broken. Now, we should be using the seq_file interface for |
| all of the proc files, but converting the legacy functions is more work |
| than most people care for and has little upside.. |
| |
| But at least we can make the non-LFS rules explicit, rather than just |
| insanely wrapping the offset or something. |
| |
| Signed-off-by: Linus Torvalds <torvalds@osdl.org> |
| Signed-off-by: Chris Wright <chrisw@sous-sol.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| fs/proc/generic.c | 47 +++++++++++++++++++++++------------------------ |
| 1 file changed, 23 insertions(+), 24 deletions(-) |
| |
| --- linux-2.6.14.5.orig/fs/proc/generic.c |
| +++ linux-2.6.14.5/fs/proc/generic.c |
| @@ -54,6 +54,18 @@ proc_file_read(struct file *file, char _ |
| ssize_t n, count; |
| char *start; |
| struct proc_dir_entry * dp; |
| + unsigned long long pos; |
| + |
| + /* |
| + * Gaah, please just use "seq_file" instead. The legacy /proc |
| + * interfaces cut loff_t down to off_t for reads, and ignore |
| + * the offset entirely for writes.. |
| + */ |
| + pos = *ppos; |
| + if (pos > MAX_NON_LFS) |
| + return 0; |
| + if (nbytes > MAX_NON_LFS - pos) |
| + nbytes = MAX_NON_LFS - pos; |
| |
| dp = PDE(inode); |
| if (!(page = (char*) __get_free_page(GFP_KERNEL))) |
| @@ -202,30 +214,17 @@ proc_file_write(struct file *file, const |
| static loff_t |
| proc_file_lseek(struct file *file, loff_t offset, int orig) |
| { |
| - lock_kernel(); |
| - |
| - switch (orig) { |
| - case 0: |
| - if (offset < 0) |
| - goto out; |
| - file->f_pos = offset; |
| - unlock_kernel(); |
| - return(file->f_pos); |
| - case 1: |
| - if (offset + file->f_pos < 0) |
| - goto out; |
| - file->f_pos += offset; |
| - unlock_kernel(); |
| - return(file->f_pos); |
| - case 2: |
| - goto out; |
| - default: |
| - goto out; |
| - } |
| - |
| -out: |
| - unlock_kernel(); |
| - return -EINVAL; |
| + loff_t retval = -EINVAL; |
| + switch (orig) { |
| + case 1: |
| + offset += file->f_pos; |
| + /* fallthrough */ |
| + case 0: |
| + if (offset < 0 || offset > MAX_NON_LFS) |
| + break; |
| + file->f_pos = retval = offset; |
| + } |
| + return retval; |
| } |
| |
| static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) |