• Nick Piggin's avatar
    mm: dirty page tracking race fix · 479db0bf
    Nick Piggin authored
    There is a race with dirty page accounting where a page may not properly
    be accounted for.
    
    clear_page_dirty_for_io() calls page_mkclean; then TestClearPageDirty.
    
    page_mkclean walks the rmaps for that page, and for each one it cleans and
    write protects the pte if it was dirty.  It uses page_check_address to
    find the pte.  That function has a shortcut to avoid the ptl if the pte is
    not present.  Unfortunately, the pte can be switched to not-present then
    back to present by other code while holding the page table lock -- this
    should not be a signal for page_mkclean to ignore that pte, because it may
    be dirty.
    
    For example, powerpc64's set_pte_at will clear a previously present pte
    before setting it to the desired value.  There may also be other code in
    core mm or in arch which do similar things.
    
    The consequence of the bug is loss of data integrity due to msync, and
    loss of dirty page accounting accuracy.  XIP's __xip_unmap could easily
    also be unreliable (depending on the exact XIP locking scheme), which can
    lead to data corruption.
    
    Fix this by having an option to always take ptl to check the pte in
    page_check_address.
    
    It's possible to retain this optimization for page_referenced and
    try_to_unmap.
    Signed-off-by: default avatarNick Piggin <npiggin@suse.de>
    Cc: Jared Hulbert <jaredeh@gmail.com>
    Cc: Carsten Otte <cotte@freenet.de>
    Cc: Hugh Dickins <hugh@veritas.com>
    Acked-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    479db0bf
filemap_xip.c 10.1 KB