[PATCH] powerpc: fix large nvram access
/dev/nvram uses the user-provided read/write size for kmalloc, which fails, if a large number is passed. This will always use a single page at most, which can be expected to succeed. Signed-off-by: Arnd Bergmann <arndb@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
d52771fce4
commit
f9ce299fc6
@ -80,80 +80,74 @@ static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
|
|||||||
static ssize_t dev_nvram_read(struct file *file, char __user *buf,
|
static ssize_t dev_nvram_read(struct file *file, char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
ssize_t len;
|
ssize_t ret;
|
||||||
char *tmp_buffer;
|
char *tmp = NULL;
|
||||||
int size;
|
ssize_t size;
|
||||||
|
|
||||||
if (ppc_md.nvram_size == NULL)
|
ret = -ENODEV;
|
||||||
return -ENODEV;
|
if (!ppc_md.nvram_size)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
size = ppc_md.nvram_size();
|
size = ppc_md.nvram_size();
|
||||||
|
if (*ppos >= size || size < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (!access_ok(VERIFY_WRITE, buf, count))
|
count = min_t(size_t, count, size - *ppos);
|
||||||
return -EFAULT;
|
count = min(count, PAGE_SIZE);
|
||||||
if (*ppos >= size)
|
|
||||||
return 0;
|
|
||||||
if (count > size)
|
|
||||||
count = size;
|
|
||||||
|
|
||||||
tmp_buffer = (char *) kmalloc(count, GFP_KERNEL);
|
ret = -ENOMEM;
|
||||||
if (!tmp_buffer) {
|
tmp = kmalloc(count, GFP_KERNEL);
|
||||||
printk(KERN_ERR "dev_read_nvram: kmalloc failed\n");
|
if (!tmp)
|
||||||
return -ENOMEM;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
len = ppc_md.nvram_read(tmp_buffer, count, ppos);
|
ret = ppc_md.nvram_read(tmp, count, ppos);
|
||||||
if ((long)len <= 0) {
|
if (ret <= 0)
|
||||||
kfree(tmp_buffer);
|
goto out;
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_to_user(buf, tmp_buffer, len)) {
|
if (copy_to_user(buf, tmp, ret))
|
||||||
kfree(tmp_buffer);
|
ret = -EFAULT;
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(tmp_buffer);
|
out:
|
||||||
return len;
|
kfree(tmp);
|
||||||
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
|
static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
ssize_t len;
|
ssize_t ret;
|
||||||
char * tmp_buffer;
|
char *tmp = NULL;
|
||||||
int size;
|
ssize_t size;
|
||||||
|
|
||||||
if (ppc_md.nvram_size == NULL)
|
ret = -ENODEV;
|
||||||
return -ENODEV;
|
if (!ppc_md.nvram_size)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
size = ppc_md.nvram_size();
|
size = ppc_md.nvram_size();
|
||||||
|
if (*ppos >= size || size < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (!access_ok(VERIFY_READ, buf, count))
|
count = min_t(size_t, count, size - *ppos);
|
||||||
return -EFAULT;
|
count = min(count, PAGE_SIZE);
|
||||||
if (*ppos >= size)
|
|
||||||
return 0;
|
|
||||||
if (count > size)
|
|
||||||
count = size;
|
|
||||||
|
|
||||||
tmp_buffer = (char *) kmalloc(count, GFP_KERNEL);
|
ret = -ENOMEM;
|
||||||
if (!tmp_buffer) {
|
tmp = kmalloc(count, GFP_KERNEL);
|
||||||
printk(KERN_ERR "dev_nvram_write: kmalloc failed\n");
|
if (!tmp)
|
||||||
return -ENOMEM;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_from_user(tmp_buffer, buf, count)) {
|
|
||||||
kfree(tmp_buffer);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = ppc_md.nvram_write(tmp_buffer, count, ppos);
|
ret = -EFAULT;
|
||||||
if ((long)len <= 0) {
|
if (copy_from_user(tmp, buf, count))
|
||||||
kfree(tmp_buffer);
|
goto out;
|
||||||
return len;
|
|
||||||
}
|
ret = ppc_md.nvram_write(tmp, count, ppos);
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree(tmp);
|
||||||
|
return ret;
|
||||||
|
|
||||||
kfree(tmp_buffer);
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dev_nvram_ioctl(struct inode *inode, struct file *file,
|
static int dev_nvram_ioctl(struct inode *inode, struct file *file,
|
||||||
|
Loading…
Reference in New Issue
Block a user