Commit ef628dc9 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] request_firmware fix

From: Manuel Estrada Sainz <ranty@debian.org>

- undo recent change, made in the believe that "buffer" was the size of
  the whole file, it is just PAGE_SIZE in size.  This was causing kernel
  memory corruption.

  - Since files are allowed to have unknown sizes, by setting their
    size to 0, we can't preallocate a buffer of their size on open.

- Adapt request_firmware() to the sysfs change.

- Adapt drivers/pci/pci-sysfs.c to the sysfs change.
parent 534d8695
......@@ -149,7 +149,7 @@ firmware_data_read(struct kobject *kobj,
if (offset + count > fw->size)
count = fw->size - offset;
memcpy(buffer + offset, fw->data + offset, count);
memcpy(buffer, fw->data + offset, count);
return count;
}
static int
......@@ -198,7 +198,7 @@ firmware_data_write(struct kobject *kobj,
if (retval)
return retval;
memcpy(fw->data + offset, buffer + offset, count);
memcpy(fw->data + offset, buffer, count);
fw->size = max_t(size_t, offset + count, fw->size);
......
......@@ -67,6 +67,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
unsigned int size = 64;
loff_t init_off = off;
/* Several chips lock up trying to read undefined config space */
if (capable(CAP_SYS_ADMIN)) {
......@@ -87,7 +88,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
while (off & 3) {
unsigned char val;
pci_read_config_byte(dev, off, &val);
buf[off] = val;
buf[off - init_off] = val;
off++;
if (--size == 0)
break;
......@@ -96,10 +97,10 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
while (size > 3) {
unsigned int val;
pci_read_config_dword(dev, off, &val);
buf[off] = val & 0xff;
buf[off + 1] = (val >> 8) & 0xff;
buf[off + 2] = (val >> 16) & 0xff;
buf[off + 3] = (val >> 24) & 0xff;
buf[off - init_off] = val & 0xff;
buf[off - init_off + 1] = (val >> 8) & 0xff;
buf[off - init_off + 2] = (val >> 16) & 0xff;
buf[off - init_off + 3] = (val >> 24) & 0xff;
off += 4;
size -= 4;
}
......@@ -107,7 +108,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
while (size > 0) {
unsigned char val;
pci_read_config_byte(dev, off, &val);
buf[off] = val;
buf[off - init_off] = val;
off++;
--size;
}
......@@ -120,6 +121,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
unsigned int size = count;
loff_t init_off = off;
if (off > 256)
return 0;
......@@ -129,24 +131,24 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
while (off & 3) {
pci_write_config_byte(dev, off, buf[off]);
pci_write_config_byte(dev, off, buf[off - init_off]);
off++;
if (--size == 0)
break;
}
while (size > 3) {
unsigned int val = buf[off];
val |= (unsigned int) buf[off + 1] << 8;
val |= (unsigned int) buf[off + 2] << 16;
val |= (unsigned int) buf[off + 3] << 24;
unsigned int val = buf[off - init_off];
val |= (unsigned int) buf[off - init_off + 1] << 8;
val |= (unsigned int) buf[off - init_off + 2] << 16;
val |= (unsigned int) buf[off - init_off + 3] << 24;
pci_write_config_dword(dev, off, val);
off += 4;
size -= 4;
}
while (size > 0) {
pci_write_config_byte(dev, off, buf[off]);
pci_write_config_byte(dev, off, buf[off - init_off]);
off++;
--size;
}
......
......@@ -47,7 +47,7 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
return ret;
count = ret;
if (copy_to_user(userbuf, buffer + offs, count))
if (copy_to_user(userbuf, buffer, count))
return -EFAULT;
pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
......@@ -83,7 +83,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
count = size - offs;
}
if (copy_from_user(buffer + offs, userbuf, count))
if (copy_from_user(buffer, userbuf, count))
return -EFAULT;
count = flush_write(dentry, buffer, offs, count);
......
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