• Russell King's avatar
    ARM: Flush user mapping on VIVT processors when copying a page · 2725898f
    Russell King authored
    Steven Walter <stevenrwalter@gmail.com> writes:
    > I've been tracking down an instance of userspace data corruption,
    > and I believe I have found a window during fork where data can be
    > lost.  The corruption is occurring on an ARMv5 system with VIVT
    > caches.  Here's the scenario in question.  Thread A is forking,
    > Thread B is running in userspace:
    >
    > Thread A: flush_cache_mm() (dup_mmap)
    > Thread B: writes to a page in the above mm
    > Thread A: pte_wrprotect() the above page (copy_one_pte)
    > Thread B: writes to the same page again
    >
    > During thread B's second write, he'll take a fault and enter the
    > do_wp_page() case.  We'll end up calling copy_page(), which notably
    > uses the kernel virtual addresses for the old and new pages.  This
    > means that the new page does not necessarily have the data from the
    > first write.  Now there are two conflicting copies of the same
    > cache-line in dcache.  If the userspace cache-line flushes before
    > the kernel cache-line, we lose the changes made during the first
    > write.  do_wp_page does call flush_dcache_page on the newly-copied
    > page, but there's still a window where the CPU could flush the
    > userspace cache-line before then.
    
    Resolve this by flushing the user mapping before copying the page
    on processors with a writeback VIVT cache.
    
    Note: this does have a performance impact, and so needs further
    consideration before being merged - can we optimize out some of
    the cache flushes if, eg, we know that the page isn't yet mapped?
    
    Thread: <e06498070903061426o5875ad13hc6328aa0d3f08ed7@mail.gmail.com>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    2725898f
copypage-v4wb.c 2.83 KB