| From: Jann Horn <jannh@google.com> |
| Date: Sat, 7 Jul 2018 04:16:33 +0200 |
| Subject: ibmasm: don't write out of bounds in read handler |
| |
| commit a0341fc1981a950c1e902ab901e98f60e0e243f3 upstream. |
| |
| This read handler had a lot of custom logic and wrote outside the bounds of |
| the provided buffer. This could lead to kernel and userspace memory |
| corruption. Just use simple_read_from_buffer() with a stack buffer. |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| Signed-off-by: Jann Horn <jannh@google.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/misc/ibmasm/ibmasmfs.c | 27 +++------------------------ |
| 1 file changed, 3 insertions(+), 24 deletions(-) |
| |
| --- a/drivers/misc/ibmasm/ibmasmfs.c |
| +++ b/drivers/misc/ibmasm/ibmasmfs.c |
| @@ -507,35 +507,14 @@ static int remote_settings_file_close(st |
| static ssize_t remote_settings_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) |
| { |
| void __iomem *address = (void __iomem *)file->private_data; |
| - unsigned char *page; |
| - int retval; |
| int len = 0; |
| unsigned int value; |
| - |
| - if (*offset < 0) |
| - return -EINVAL; |
| - if (count == 0 || count > 1024) |
| - return 0; |
| - if (*offset != 0) |
| - return 0; |
| - |
| - page = (unsigned char *)__get_free_page(GFP_KERNEL); |
| - if (!page) |
| - return -ENOMEM; |
| + char lbuf[20]; |
| |
| value = readl(address); |
| - len = sprintf(page, "%d\n", value); |
| - |
| - if (copy_to_user(buf, page, len)) { |
| - retval = -EFAULT; |
| - goto exit; |
| - } |
| - *offset += len; |
| - retval = len; |
| + len = snprintf(lbuf, sizeof(lbuf), "%d\n", value); |
| |
| -exit: |
| - free_page((unsigned long)page); |
| - return retval; |
| + return simple_read_from_buffer(buf, count, offset, lbuf, len); |
| } |
| |
| static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset) |