Skip to content
  • Xiao Guangrong's avatar
    mm: mmu_notifier: re-fix freed page still mapped in secondary MMU · d34883d4
    Xiao Guangrong authored
    Commit 751efd86 ("mmu_notifier_unregister NULL Pointer deref and
    multiple ->release()") breaks the fix 3ad3d901 ("mm: mmu_notifier:
    fix freed page still mapped in secondary MMU").
    
    Since hlist_for_each_entry_rcu() is changed now, we can not revert that
    patch directly, so this patch reverts the commit and simply fix the bug
    spotted by that patch
    
    This bug spotted by commit 751efd86 is:
    
        There is a race condition between mmu_notifier_unregister() and
        __mmu_notifier_release().
    
        Assume two tasks, one calling mmu_notifier_unregister() as a result
        of a filp_close() ->flush() callout (task A), and the other calling
        mmu_notifier_release() from an mmput() (task B).
    
                            A                               B
        t1                                            srcu_read_lock()
        t2            if (!hlist_unhashed())
        t3                                            srcu_read_unlock()
        t4            srcu_read_lock()
        t5                                            hlist_del_init_rcu()
        t6                                            synchronize_srcu()
        t7            srcu_read_unlock()
        t8            hlist_del_rcu()  <--- NULL pointer deref.
    
    This can be fixed by using hlist_del_init_rcu instead of hlist_del_rcu.
    
    The another issue spotted in the commit is "multiple ->release()
    callouts", we needn't care it too much because it is really rare (e.g,
    can not happen on kvm since mmu-notify is unregistered after
    exit_mmap()) and the later call of multiple ->release should be fast
    since all the pages have already been released by the first call.
    Anyway, this issue should be fixed in a separate patch.
    
    -stable suggestions: Any version that has commit 751efd86
    
     need to be
    backported.  I find the oldest version has this commit is 3.0-stable.
    
    [akpm@linux-foundation.org: tweak comments]
    Signed-off-by: default avatarXiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
    Tested-by: default avatarRobin Holt <holt@sgi.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    d34883d4