lkml.org 
[lkml]   [2008]   [Oct]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    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


    \
     
     \ /
      Last update: 2008-10-07 12:59    [W:2.701 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site