• Lars Persson's avatar
    MIPS: Fix race condition in lazy cache flushing. · 4d46a67a
    Lars Persson authored
    The lazy cache flushing implemented in the MIPS kernel suffers from a
    race condition that is exposed by do_set_pte() in mm/memory.c.
    
    A pre-condition is a file-system that writes to the page from the CPU
    in its readpage method and then calls flush_dcache_page(). One example
    is ubifs. Another pre-condition is that the dcache flush is postponed
    in __flush_dcache_page().
    
    Upon a page fault for an executable mapping not existing in the
    page-cache, the following will happen:
    1. Write to the page
    2. flush_dcache_page
    3. flush_icache_page
    4. set_pte_at
    5. update_mmu_cache (commits the flush of a dcache-dirty page)
    
    Between steps 4 and 5 another thread can hit the same page and it will
    encounter a valid pte. Because the data still is in the L1 dcache the CPU
    will fetch stale data from L2 into the icache and execute garbage.
    
    This fix moves the commit of the cache flush to step 3 to close the
    race window. It also reduces the amount of flushes on non-executable
    mappings because we never enter __flush_dcache_page() for non-aliasing
    CPUs.
    
    Regressions can occur in drivers that mistakenly relies on the
    flush_dcache_page() in get_user_pages() for DMA operations.
    
    [ralf@linux-mips.org: Folded in patch 9346 to fix highmem issue.]
    Signed-off-by: default avatarLars Persson <larper@axis.com>
    Cc: linux-mips@linux-mips.org
    Cc: paul.burton@imgtec.com
    Cc: linux-kernel@vger.kernel.org
    Patchwork: https://patchwork.linux-mips.org/patch/9346/
    Patchwork: https://patchwork.linux-mips.org/patch/9738/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
    4d46a67a
cacheflush.h 4.94 KB