• Vineet Gupta's avatar
    ARC: mm: do_page_fault fixes #1: relinquish mmap_sem if signal arrives while handle_mm_fault · 4d447455
    Vineet Gupta authored
    do_page_fault() forgot to relinquish mmap_sem if a signal came while
    handling handle_mm_fault() - due to say a ctl+c or oom etc.
    This would later cause a deadlock by acquiring it twice.
    
    This came to light when running libc testsuite tst-tls3-malloc test but
    is likely also the cause for prior seen LTP failures. Using lockdep
    clearly showed what the issue was.
    
    | # while true; do ./tst-tls3-malloc ; done
    | Didn't expect signal from child: got `Segmentation fault'
    | ^C
    | ============================================
    | WARNING: possible recursive locking detected
    | 4.17.0+ #25 Not tainted
    | --------------------------------------------
    | tst-tls3-malloc/510 is trying to acquire lock:
    | 606c7728 (&mm->mmap_sem){++++}, at: __might_fault+0x28/0x5c
    |
    |but task is already holding lock:
    |606c7728 (&mm->mmap_sem){++++}, at: do_page_fault+0x9c/0x2a0
    |
    | other info that might help us debug this:
    |  Possible unsafe locking scenario:
    |
    |       CPU0
    |       ----
    |  lock(&mm->mmap_sem);
    |  lock(&mm->mmap_sem);
    |
    | *** DEADLOCK ***
    |
    
    ------------------------------------------------------------
    What the change does is not obvious (note to myself)
    
    prior code was
    
    | do_page_fault
    |
    |   down_read()		<-- lock taken
    |   handle_mm_fault	<-- signal pending as this runs
    |   if fatal_signal_pending
    |       if VM_FAULT_ERROR
    |           up_read
    |       if user_mode
    |          return	<-- lock still held, this was the BUG
    
    New code
    
    | do_page_fault
    |
    |   down_read()		<-- lock taken
    |   handle_mm_fault	<-- signal pending as this runs
    |   if fatal_signal_pending
    |       if VM_FAULT_RETRY
    |          return       <-- not same case as above, but still OK since
    |                           core mm already relinq lock for FAULT_RETRY
    |    ...
    |
    |   < Now falls through for bug case above >
    |
    |   up_read()		<-- lock relinquished
    
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
    4d447455
fault.c 5.58 KB