Messages in this thread Patch in this message | | | From | (Eric W. Biederman) | Date | Tue, 07 Oct 2008 03:49:29 -0700 | Subject | [PATCH 1/3] sysfs: Remove lock ordering violation in sysfs_chmod_file. |
| |
It is a wee bit subtle but sysfs_get_dentry grabs inode->i_mutex. of potentially all of the parents of sd. So I can not hold the inode mutex of the directory while it is called.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> --- fs/sysfs/file.c | 37 ++++++++++++++++--------------------- 1 files changed, 16 insertions(+), 21 deletions(-)
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 091c0de..8b572b6 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -582,7 +582,6 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { struct sysfs_dirent *victim_sd = NULL; struct super_block *sb; - struct inode * inode = NULL; struct iattr newattrs; int rc; @@ -591,42 +590,38 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) if (!victim_sd) goto out; - rc = -ENOENT; - mutex_lock(&sysfs_mutex); - inode = sysfs_get_inode(victim_sd); - mutex_unlock(&sysfs_mutex); - if (!inode) - goto out; - mutex_lock(&sysfs_rename_mutex); sysfs_grab_supers(); - mutex_lock(&inode->i_mutex); - - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - newattrs.ia_ctime = current_fs_time(inode->i_sb); - rc = sysfs_sd_setattr(victim_sd, inode, &newattrs); - if (rc) - goto out_unlock; list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { + struct dentry * victim; + struct inode * inode; + /* Ignore it when the dentry does not exist on the * target superblock. */ - struct dentry * victim = sysfs_get_dentry(sb, victim_sd); + mutex_lock(&sysfs_mutex); + victim = sysfs_get_dentry(sb, victim_sd); + mutex_unlock(&sysfs_mutex); if (IS_ERR(victim)) continue; - fsnotify_change(victim, newattrs.ia_valid); + inode = victim->d_inode; + mutex_lock(&inode->i_mutex); + newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); + newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; + newattrs.ia_ctime = current_fs_time(inode->i_sb); + rc = sysfs_sd_setattr(victim_sd, inode, &newattrs); + if (!rc) + fsnotify_change(victim, newattrs.ia_valid); + + mutex_unlock(&inode->i_mutex); dput(victim); } - out_unlock: - mutex_unlock(&inode->i_mutex); sysfs_release_supers(); mutex_unlock(&sysfs_rename_mutex); out: - iput(inode); sysfs_put(victim_sd); return rc; } -- 1.5.3.rc6.17.g1911
| |