mm: ksm: fix use-after-free kasan report in ksm_might_need_to_copy v5

The non linearity of swap entries that PageKsm generates requires
special revalidation of the anon_vma pointed by the swapcache.

All detailed commentary can be found in code comments that are more
important than this commit header.

This should fix the crash reported here:
https://lkml.kernel.org/r/81416741-d11c-61d4-26f9-4546dd874581@huawei.com

v3: the two previous attempts weren't still fully correct. Hugh
    Dickins pointed two remaining bugs that this new version addresses
    through the forced reinitialization of page->mapping in the
    !page_mapped case, and with the RCU read lock for the !!page_mapped
    case.

v4: Hugh Dickins reported clearing the page->mapping of THP swapcache
    didn't work as intended since it failed to clear PageAnon which checks
    the head. Luckily THP swapcache cannot point to a swapentry created by
    a PageKsm swapout, so there's no need of re-initializing the
    page->mapping of a THP.

v5: page->index was read from the tail page, but it's only valid in
    the head page, so instead of doing the math on the linear subpage
    index to pass it, check the PageTransCompound() early on.

Fixes: e1c63e110f97 ("mm: ksm: fix use-after-free kasan report in ksm_might_need_to_copy")
Fixes: ba6f0ff3981e ("ksm: fix ksm swapin time optimization")
Cc: stable@kernel.org
Co-developed-by: Hugh Dickins <hughd@google.com>
Reported-by: Nanyong Sun <sunnanyong@huawei.com>
Reported-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
2 files changed