Commit 78fdb0c4 authored by Michael E. Brown's avatar Michael E. Brown Committed by Linus Torvalds

[PATCH] sysfs module unload race fix for bin_attributes

 -  Add module locking to sysfs bin_attribute files. Update all in-tree
    users to set module owner.

	Compile tested. booted. stress tests pass:

while true; do modprobe mymod; rmmod mymod; done &
while true; do hexdump -C /sys/path/to/sysfs/binary/file; done
parent 17d5007f
......@@ -254,7 +254,7 @@ firmware_data_write(struct kobject *kobj,
return retval;
}
static struct bin_attribute firmware_attr_data_tmpl = {
.attr = {.name = "data", .mode = 0644},
.attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
.size = 0,
.read = firmware_data_read,
.write = firmware_data_write,
......
......@@ -155,6 +155,7 @@ static struct bin_attribute eeprom_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = EEPROM_SIZE,
.read = eeprom_read,
......
......@@ -402,6 +402,7 @@ static struct bin_attribute sysfs_fw_dump_attr = {
.attr = {
.name = "fw_dump",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 0,
.read = qla2x00_sysfs_read_fw_dump,
......@@ -415,6 +416,7 @@ static struct bin_attribute sysfs_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = sizeof(nvram_t),
.read = qla2x00_sysfs_read_nvram,
......
......@@ -101,19 +101,27 @@ static int open(struct inode * inode, struct file * file)
if (!kobj || !attr)
goto Done;
/* Grab the module reference for this attribute if we have one */
error = -ENODEV;
if (!try_module_get(attr->attr.owner))
goto Done;
error = -EACCES;
if ((file->f_mode & FMODE_WRITE) && !attr->write)
goto Done;
goto Error;
if ((file->f_mode & FMODE_READ) && !attr->read)
goto Done;
goto Error;
error = -ENOMEM;
file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!file->private_data)
goto Done;
goto Error;
error = 0;
goto Done;
Error:
module_put(attr->attr.owner);
Done:
if (error && kobj)
kobject_put(kobj);
......@@ -123,10 +131,12 @@ static int open(struct inode * inode, struct file * file)
static int release(struct inode * inode, struct file * file)
{
struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
struct bin_attribute * attr = file->f_dentry->d_fsdata;
u8 * buffer = file->private_data;
if (kobj)
kobject_put(kobj);
module_put(attr->attr.owner);
kfree(buffer);
return 0;
}
......
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