[PATCH v2 0/4] kasan: Fix ordering between MTE tag colouring and page->flags
Will Deacon
will at kernel.org
Fri Jul 8 06:31:06 PDT 2022
On Fri, Jun 10, 2022 at 04:21:37PM +0100, Catalin Marinas wrote:
> Hi,
>
> That's a second attempt on fixing the race race between setting the
> allocation (in-memory) tags in a page and the corresponding logical tag
> in page->flags. Initial version here:
>
> https://lore.kernel.org/r/20220517180945.756303-1-catalin.marinas@arm.com
>
> This new series does not introduce any new GFP flags but instead always
> skips unpoisoning of the user pages (we already skip the poisoning on
> free). Any unpoisoned page will have the page->flags tag reset.
>
> For the background:
>
> On a system with MTE and KASAN_HW_TAGS enabled, when a page is allocated
> kasan_unpoison_pages() sets a random tag and saves it in page->flags so
> that page_to_virt() re-creates the correct tagged pointer. We need to
> ensure that the in-memory tags are visible before setting the
> page->flags:
>
> P0 (__kasan_unpoison_range): P1 (access via virt_to_page):
> Wtags=x Rflags=x
> | |
> | DMB | address dependency
> V V
> Wflags=x Rtags=x
>
> The first patch changes the order of page unpoisoning with the tag
> storing in page->flags. page_kasan_tag_set() has the right barriers
> through try_cmpxchg().
>
> If a page is mapped in user-space with PROT_MTE, the architecture code
> will set the allocation tag to 0 and a subsequent page_to_virt()
> dereference will fault. We currently try to fix this by resetting the
> tag in page->flags so that it is 0xff (match-all, not faulting).
> However, setting the tags and flags can race with another CPU reading
> the flags (page_to_virt()) and barriers can't help, e.g.:
>
> P0 (mte_sync_page_tags): P1 (memcpy from virt_to_page):
> Rflags!=0xff
> Wflags=0xff
> DMB (doesn't help)
> Wtags=0
> Rtags=0 // fault
>
> Since clearing the flags in the arch code doesn't work, to do this at
> page allocation time when __GFP_SKIP_KASAN_UNPOISON is passed.
I've picked this up, thanks.
An alternative solution might be to use a seqlock (if you can find somewhere
to put it) so that virt_to_page() spins briefly while the tags and flags
are being updated.
Will
More information about the linux-arm-kernel
mailing list