From: Catalin Marinas <catalin.marinas@arm.com> To: Andrey Ryabinin <ryabinin.a.a@gmail.com>, Andrey Konovalov <andreyknvl@gmail.com> Cc: Will Deacon <will@kernel.org>, Vincenzo Frascino <vincenzo.frascino@arm.com>, Peter Collingbourne <pcc@google.com>, kasan-dev@googlegroups.com, linux-mm@kvack.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 2/3] mm: kasan: Reset the tag on pages intended for user Date: Tue, 17 May 2022 19:09:44 +0100 [thread overview] Message-ID: <20220517180945.756303-3-catalin.marinas@arm.com> (raw) In-Reply-To: <20220517180945.756303-1-catalin.marinas@arm.com> On allocation kasan colours a page with a random tag and stores such tag in page->flags so that a subsequent page_to_virt() reconstructs the correct tagged pointer. However, when such page is mapped in user-space with PROT_MTE, the kernel's initial tag is overridden. Ensure that such pages have the tag reset (match-all) at allocation time since any late clearing of the tag is racy with other page_to_virt() dereferencing. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com> Cc: Andrey Konovalov <andreyknvl@gmail.com> Cc: Vincenzo Frascino <vincenzo.frascino@arm.com> --- include/linux/gfp.h | 10 +++++++--- mm/page_alloc.c | 9 ++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 3e3d36fc2109..88b1d4fe4dcb 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -58,13 +58,15 @@ struct vm_area_struct; #define ___GFP_SKIP_ZERO 0x1000000u #define ___GFP_SKIP_KASAN_UNPOISON 0x2000000u #define ___GFP_SKIP_KASAN_POISON 0x4000000u +#define ___GFP_PAGE_KASAN_TAG_RESET 0x8000000u #else #define ___GFP_SKIP_ZERO 0 #define ___GFP_SKIP_KASAN_UNPOISON 0 #define ___GFP_SKIP_KASAN_POISON 0 +#define ___GFP_PAGE_KASAN_TAG_RESET 0 #endif #ifdef CONFIG_LOCKDEP -#define ___GFP_NOLOCKDEP 0x8000000u +#define ___GFP_NOLOCKDEP 0x10000000u #else #define ___GFP_NOLOCKDEP 0 #endif @@ -259,12 +261,13 @@ struct vm_area_struct; #define __GFP_SKIP_ZERO ((__force gfp_t)___GFP_SKIP_ZERO) #define __GFP_SKIP_KASAN_UNPOISON ((__force gfp_t)___GFP_SKIP_KASAN_UNPOISON) #define __GFP_SKIP_KASAN_POISON ((__force gfp_t)___GFP_SKIP_KASAN_POISON) +#define __GFP_PAGE_KASAN_TAG_RESET ((__force gfp_t)___GFP_PAGE_KASAN_TAG_RESET) /* Disable lockdep for GFP context tracking */ #define __GFP_NOLOCKDEP ((__force gfp_t)___GFP_NOLOCKDEP) /* Room for N __GFP_FOO bits */ -#define __GFP_BITS_SHIFT (27 + IS_ENABLED(CONFIG_LOCKDEP)) +#define __GFP_BITS_SHIFT (28 + IS_ENABLED(CONFIG_LOCKDEP)) #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) /** @@ -343,7 +346,8 @@ struct vm_area_struct; #define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM) #define GFP_NOIO (__GFP_RECLAIM) #define GFP_NOFS (__GFP_RECLAIM | __GFP_IO) -#define GFP_USER (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL) +#define GFP_USER (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \ + __GFP_PAGE_KASAN_TAG_RESET) #define GFP_DMA __GFP_DMA #define GFP_DMA32 __GFP_DMA32 #define GFP_HIGHUSER (GFP_USER | __GFP_HIGHMEM) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0e42038382c1..f9018a84f4e3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2382,6 +2382,7 @@ inline void post_alloc_hook(struct page *page, unsigned int order, bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags) && !should_skip_init(gfp_flags); bool init_tags = init && (gfp_flags & __GFP_ZEROTAGS); + int i; set_page_private(page, 0); set_page_refcounted(page); @@ -2407,8 +2408,6 @@ inline void post_alloc_hook(struct page *page, unsigned int order, * should be initialized as well). */ if (init_tags) { - int i; - /* Initialize both memory and tags. */ for (i = 0; i != 1 << order; ++i) tag_clear_highpage(page + i); @@ -2430,7 +2429,11 @@ inline void post_alloc_hook(struct page *page, unsigned int order, /* Propagate __GFP_SKIP_KASAN_POISON to page flags. */ if (kasan_hw_tags_enabled() && (gfp_flags & __GFP_SKIP_KASAN_POISON)) SetPageSkipKASanPoison(page); - + /* if match-all page address required, reset the tag */ + if (gfp_flags & __GFP_PAGE_KASAN_TAG_RESET) { + for (i = 0; i != 1 << order; ++i) + page_kasan_tag_reset(page + i); + }; set_page_owner(page, order, gfp_flags); page_table_check_alloc(page, order); }
WARNING: multiple messages have this Message-ID (diff)
From: Catalin Marinas <catalin.marinas@arm.com> To: Andrey Ryabinin <ryabinin.a.a@gmail.com>, Andrey Konovalov <andreyknvl@gmail.com> Cc: Will Deacon <will@kernel.org>, Vincenzo Frascino <vincenzo.frascino@arm.com>, Peter Collingbourne <pcc@google.com>, kasan-dev@googlegroups.com, linux-mm@kvack.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 2/3] mm: kasan: Reset the tag on pages intended for user Date: Tue, 17 May 2022 19:09:44 +0100 [thread overview] Message-ID: <20220517180945.756303-3-catalin.marinas@arm.com> (raw) In-Reply-To: <20220517180945.756303-1-catalin.marinas@arm.com> On allocation kasan colours a page with a random tag and stores such tag in page->flags so that a subsequent page_to_virt() reconstructs the correct tagged pointer. However, when such page is mapped in user-space with PROT_MTE, the kernel's initial tag is overridden. Ensure that such pages have the tag reset (match-all) at allocation time since any late clearing of the tag is racy with other page_to_virt() dereferencing. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com> Cc: Andrey Konovalov <andreyknvl@gmail.com> Cc: Vincenzo Frascino <vincenzo.frascino@arm.com> --- include/linux/gfp.h | 10 +++++++--- mm/page_alloc.c | 9 ++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 3e3d36fc2109..88b1d4fe4dcb 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -58,13 +58,15 @@ struct vm_area_struct; #define ___GFP_SKIP_ZERO 0x1000000u #define ___GFP_SKIP_KASAN_UNPOISON 0x2000000u #define ___GFP_SKIP_KASAN_POISON 0x4000000u +#define ___GFP_PAGE_KASAN_TAG_RESET 0x8000000u #else #define ___GFP_SKIP_ZERO 0 #define ___GFP_SKIP_KASAN_UNPOISON 0 #define ___GFP_SKIP_KASAN_POISON 0 +#define ___GFP_PAGE_KASAN_TAG_RESET 0 #endif #ifdef CONFIG_LOCKDEP -#define ___GFP_NOLOCKDEP 0x8000000u +#define ___GFP_NOLOCKDEP 0x10000000u #else #define ___GFP_NOLOCKDEP 0 #endif @@ -259,12 +261,13 @@ struct vm_area_struct; #define __GFP_SKIP_ZERO ((__force gfp_t)___GFP_SKIP_ZERO) #define __GFP_SKIP_KASAN_UNPOISON ((__force gfp_t)___GFP_SKIP_KASAN_UNPOISON) #define __GFP_SKIP_KASAN_POISON ((__force gfp_t)___GFP_SKIP_KASAN_POISON) +#define __GFP_PAGE_KASAN_TAG_RESET ((__force gfp_t)___GFP_PAGE_KASAN_TAG_RESET) /* Disable lockdep for GFP context tracking */ #define __GFP_NOLOCKDEP ((__force gfp_t)___GFP_NOLOCKDEP) /* Room for N __GFP_FOO bits */ -#define __GFP_BITS_SHIFT (27 + IS_ENABLED(CONFIG_LOCKDEP)) +#define __GFP_BITS_SHIFT (28 + IS_ENABLED(CONFIG_LOCKDEP)) #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) /** @@ -343,7 +346,8 @@ struct vm_area_struct; #define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM) #define GFP_NOIO (__GFP_RECLAIM) #define GFP_NOFS (__GFP_RECLAIM | __GFP_IO) -#define GFP_USER (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL) +#define GFP_USER (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \ + __GFP_PAGE_KASAN_TAG_RESET) #define GFP_DMA __GFP_DMA #define GFP_DMA32 __GFP_DMA32 #define GFP_HIGHUSER (GFP_USER | __GFP_HIGHMEM) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0e42038382c1..f9018a84f4e3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2382,6 +2382,7 @@ inline void post_alloc_hook(struct page *page, unsigned int order, bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags) && !should_skip_init(gfp_flags); bool init_tags = init && (gfp_flags & __GFP_ZEROTAGS); + int i; set_page_private(page, 0); set_page_refcounted(page); @@ -2407,8 +2408,6 @@ inline void post_alloc_hook(struct page *page, unsigned int order, * should be initialized as well). */ if (init_tags) { - int i; - /* Initialize both memory and tags. */ for (i = 0; i != 1 << order; ++i) tag_clear_highpage(page + i); @@ -2430,7 +2429,11 @@ inline void post_alloc_hook(struct page *page, unsigned int order, /* Propagate __GFP_SKIP_KASAN_POISON to page flags. */ if (kasan_hw_tags_enabled() && (gfp_flags & __GFP_SKIP_KASAN_POISON)) SetPageSkipKASanPoison(page); - + /* if match-all page address required, reset the tag */ + if (gfp_flags & __GFP_PAGE_KASAN_TAG_RESET) { + for (i = 0; i != 1 << order; ++i) + page_kasan_tag_reset(page + i); + }; set_page_owner(page, order, gfp_flags); page_table_check_alloc(page, order); } _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2022-05-17 18:09 UTC|newest] Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-05-17 18:09 [PATCH 0/3] kasan: Fix ordering between MTE tag colouring and page->flags Catalin Marinas 2022-05-17 18:09 ` Catalin Marinas 2022-05-17 18:09 ` [PATCH 1/3] mm: kasan: Ensure the tags are visible before the tag in page->flags Catalin Marinas 2022-05-17 18:09 ` Catalin Marinas 2022-05-21 22:14 ` Andrey Konovalov 2022-05-21 22:14 ` Andrey Konovalov 2022-05-17 18:09 ` Catalin Marinas [this message] 2022-05-17 18:09 ` [PATCH 2/3] mm: kasan: Reset the tag on pages intended for user Catalin Marinas 2022-05-21 22:15 ` Andrey Konovalov 2022-05-21 22:15 ` Andrey Konovalov 2022-05-17 18:09 ` [PATCH 3/3] arm64: kasan: Revert "arm64: mte: reset the page tag in page->flags" Catalin Marinas 2022-05-17 18:09 ` Catalin Marinas 2022-05-21 22:16 ` Andrey Konovalov 2022-05-21 22:16 ` Andrey Konovalov 2022-05-19 21:45 ` [PATCH 0/3] kasan: Fix ordering between MTE tag colouring and page->flags Andrey Konovalov 2022-05-19 21:45 ` Andrey Konovalov 2022-05-20 13:01 ` Catalin Marinas 2022-05-20 13:01 ` Catalin Marinas 2022-05-21 22:20 ` Andrey Konovalov 2022-05-21 22:20 ` Andrey Konovalov 2022-05-25 15:45 ` Catalin Marinas 2022-05-25 15:45 ` Catalin Marinas 2022-05-25 17:41 ` Andrey Konovalov 2022-05-25 17:41 ` Andrey Konovalov 2022-05-26 12:24 ` Catalin Marinas 2022-05-26 12:24 ` Catalin Marinas 2022-05-31 17:16 ` Andrey Konovalov 2022-05-31 17:16 ` Andrey Konovalov 2022-06-09 18:32 ` Catalin Marinas 2022-06-09 18:32 ` Catalin Marinas 2022-06-09 18:40 ` Andrey Konovalov 2022-06-09 18:40 ` Andrey Konovalov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220517180945.756303-3-catalin.marinas@arm.com \ --to=catalin.marinas@arm.com \ --cc=andreyknvl@gmail.com \ --cc=kasan-dev@googlegroups.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-mm@kvack.org \ --cc=pcc@google.com \ --cc=ryabinin.a.a@gmail.com \ --cc=vincenzo.frascino@arm.com \ --cc=will@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.