From: Manuel Estrada Sainz - 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. drivers/base/firmware_class.c | 4 ++-- drivers/pci/pci-sysfs.c | 26 ++++++++++++++------------ fs/sysfs/bin.c | 4 ++-- 3 files changed, 18 insertions(+), 16 deletions(-) diff -puN drivers/base/firmware_class.c~sysfs-bin-unbreak-3 drivers/base/firmware_class.c --- 25/drivers/base/firmware_class.c~sysfs-bin-unbreak-3 2003-08-10 19:42:56.000000000 -0700 +++ 25-akpm/drivers/base/firmware_class.c 2003-08-10 19:42:56.000000000 -0700 @@ -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); diff -puN drivers/pci/pci-sysfs.c~sysfs-bin-unbreak-3 drivers/pci/pci-sysfs.c --- 25/drivers/pci/pci-sysfs.c~sysfs-bin-unbreak-3 2003-08-10 19:42:56.000000000 -0700 +++ 25-akpm/drivers/pci/pci-sysfs.c 2003-08-10 19:42:56.000000000 -0700 @@ -67,6 +67,7 @@ pci_read_config(struct kobject *kobj, ch { 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, ch 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, ch 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, ch 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, c { 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, c } 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; } diff -puN fs/sysfs/bin.c~sysfs-bin-unbreak-3 fs/sysfs/bin.c --- 25/fs/sysfs/bin.c~sysfs-bin-unbreak-3 2003-08-10 19:42:56.000000000 -0700 +++ 25-akpm/fs/sysfs/bin.c 2003-08-10 19:42:56.000000000 -0700 @@ -47,7 +47,7 @@ read(struct file * file, char __user * u 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, 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); _