Skip to content
  • Junxiao Bi's avatar
    configfs: fix race between dentry put and lookup · 7a4ca203
    Junxiao Bi authored
    
    
    commit 76ae281f6307331aa063288edb6422ae99f435f0 upstream.
    
    A race window in configfs, it starts from one dentry is UNHASHED and end
    before configfs_d_iput is called.  In this window, if a lookup happen,
    since the original dentry was UNHASHED, so a new dentry will be
    allocated, and then in configfs_attach_attr(), sd->s_dentry will be
    updated to the new dentry.  Then in configfs_d_iput(),
    BUG_ON(sd->s_dentry != dentry) will be triggered and system panic.
    
    sys_open:                     sys_close:
     ...                           fput
                                    dput
                                     dentry_kill
                                      __d_drop <--- dentry unhashed here,
                                               but sd->dentry still point
                                               to this dentry.
    
     lookup_real
      configfs_lookup
       configfs_attach_attr---> update sd->s_dentry
                                to new allocated dentry here.
    
                                       d_kill
                                         configfs_d_iput <--- BUG_ON(sd->s_dentry != dentry)
                                                         triggered here.
    
    To fix it, change configfs_d_iput to not update sd->s_dentry if
    sd->s_count > 2, that means there are another dentry is using the sd
    beside the one that is going to be put.  Use configfs_dirent_lock in
    configfs_attach_attr to sync with configfs_d_iput.
    
    With the following steps, you can reproduce the bug.
    
    1. enable ocfs2, this will mount configfs at /sys/kernel/config and
       fill configure in it.
    
    2. run the following script.
    	while [ 1 ]; do cat /sys/kernel/config/cluster/$your_cluster_name/idle_timeout_ms > /dev/null; done &
    	while [ 1 ]; do cat /sys/kernel/config/cluster/$your_cluster_name/idle_timeout_ms > /dev/null; done &
    
    Signed-off-by: default avatarJunxiao Bi <junxiao.bi@oracle.com>
    Cc: Joel Becker <jlbec@evilplan.org>
    Cc: Al Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    7a4ca203