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