Commit 2c0e195b authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] sysfs: pin kobjects to fix use-after-free crashes

From: Maneesh Soni <maneesh@in.ibm.com>

Fix a sysfs use-after-free crash.  The problem we have is of the kobject
going away while we have a live dentry (the corresponding sysfs directory)
still pointing to it throuh d_fsdata pointer.  The patch makes sure to keep
the kobject alive by taking a reference to it during the life-time of
corresponding dentry.


o The following pins the kobject when sysfs assigns dentry and inode to
  the kobject. This ensures that kobject is alive during the life time of
  the dentry and inode, and people holding ref. to the dentry can access the
  kobject without any problems.

o The ref. taken for the kobject is released through dentry->d_op->d_iput()
  call when the dentry ref. count drops to zero and it is being freed. For
  this sysfs_dentry_operations is introduced.

For testing one has to run the following test on a SMP box:

1) Do insmod/rmmod "dummy.o" network driver in a forever loop.

2) Parallely do "find /sys/class/net | xargs cat" also in a forever loop.
parent b67cee68
...@@ -20,6 +20,18 @@ static int init_dir(struct inode * inode) ...@@ -20,6 +20,18 @@ static int init_dir(struct inode * inode)
return 0; return 0;
} }
static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
{
struct kobject * kobj = dentry->d_fsdata;
if (kobj)
kobject_put(kobj);
iput(inode);
}
static struct dentry_operations sysfs_dentry_operations = {
.d_iput = &sysfs_d_iput,
};
static int create_dir(struct kobject * k, struct dentry * p, static int create_dir(struct kobject * k, struct dentry * p,
const char * n, struct dentry ** d) const char * n, struct dentry ** d)
...@@ -33,7 +45,8 @@ static int create_dir(struct kobject * k, struct dentry * p, ...@@ -33,7 +45,8 @@ static int create_dir(struct kobject * k, struct dentry * p,
S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO, S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO,
init_dir); init_dir);
if (!error) { if (!error) {
(*d)->d_fsdata = k; (*d)->d_op = &sysfs_dentry_operations;
(*d)->d_fsdata = kobject_get(k);
p->d_inode->i_nlink++; p->d_inode->i_nlink++;
} }
dput(*d); dput(*d);
......
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