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: 1da177e4c3
("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
bc20ab941e
commit
ba20e67aee
|
@ -507,35 +507,14 @@ static int remote_settings_file_close(struct inode *inode, struct file *file)
|
||||||
static ssize_t remote_settings_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
|
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;
|
void __iomem *address = (void __iomem *)file->private_data;
|
||||||
unsigned char *page;
|
|
||||||
int retval;
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
|
char lbuf[20];
|
||||||
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;
|
|
||||||
|
|
||||||
value = readl(address);
|
value = readl(address);
|
||||||
len = sprintf(page, "%d\n", value);
|
len = snprintf(lbuf, sizeof(lbuf), "%d\n", value);
|
||||||
|
|
||||||
if (copy_to_user(buf, page, len)) {
|
return simple_read_from_buffer(buf, count, offset, lbuf, len);
|
||||||
retval = -EFAULT;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
*offset += len;
|
|
||||||
retval = len;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
free_page((unsigned long)page);
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset)
|
static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user