• Nick Piggin's avatar
    mm: fix race in COW logic · 945754a1
    Nick Piggin authored
    There is a race in the COW logic.  It contains a shortcut to avoid the
    COW and reuse the page if we have the sole reference on the page,
    however it is possible to have two racing do_wp_page()ers with one
    causing the other to mistakenly believe it is safe to take the shortcut
    when it is not.  This could lead to data corruption.
    
    Process 1 and process2 each have a wp pte of the same anon page (ie.
    one forked the other).  The page's mapcount is 2.  Then they both
    attempt to write to it around the same time...
    
      proc1				proc2 thr1			proc2 thr2
      CPU0				CPU1				CPU3
      do_wp_page()			do_wp_page()
    				 trylock_page()
    				  can_share_swap_page()
    				   load page mapcount (==2)
    				  reuse = 0
    				 pte unlock
    				 copy page to new_page
    				 pte lock
    				 page_remove_rmap(page);
       trylock_page()
        can_share_swap_page()
         load page mapcount (==1)
        reuse = 1
       ptep_set_access_flags (allow W)
    
      write private key into page
    								read from page
    				ptep_clear_flush()
    				set_pte_at(pte of new_page)
    
    Fix this by moving the page_remove_rmap of the old page after the pte
    clear and flush.  Potentially the entire branch could be moved down
    here, but in order to stay consistent, I won't (should probably move all
    the *_mm_counter stuff with one patch).
    Signed-off-by: default avatarNick Piggin <npiggin@suse.de>
    Acked-by: default avatarHugh Dickins <hugh@veritas.com>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    945754a1
memory.c 77.8 KB