Skip to content

Commit 4748b6d

Browse files
xairygregkh
authored andcommitted
kasan: fix per-page tags for non-page_alloc pages
commit cf10bd4 upstream. To allow performing tag checks on page_alloc addresses obtained via page_address(), tag-based KASAN modes store tags for page_alloc allocations in page->flags. Currently, the default tag value stored in page->flags is 0x00. Therefore, page_address() returns a 0x00ffff... address for pages that were not allocated via page_alloc. This might cause problems. A particular case we encountered is a conflict with KFENCE. If a KFENCE-allocated slab object is being freed via kfree(page_address(page) + offset), the address passed to kfree() will get tagged with 0x00 (as slab pages keep the default per-page tags). This leads to is_kfence_address() check failing, and a KFENCE object ending up in normal slab freelist, which causes memory corruptions. This patch changes the way KASAN stores tag in page-flags: they are now stored xor'ed with 0xff. This way, KASAN doesn't need to initialize per-page flags for every created page, which might be slow. With this change, page_address() returns natively-tagged (with 0xff) pointers for pages that didn't have tags set explicitly. This patch fixes the encountered conflict with KFENCE and prevents more similar issues that can occur in the future. Link: https://lkml.kernel.org/r/1a41abb11c51b264511d9e71c303bb16d5cb367b.1615475452.git.andreyknvl@google.com Fixes: 2813b9c ("kasan, mm, arm64: tag non slab memory allocated via pagealloc") Signed-off-by: Andrey Konovalov <[email protected]> Reviewed-by: Marco Elver <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Will Deacon <[email protected]> Cc: Vincenzo Frascino <[email protected]> Cc: Dmitry Vyukov <[email protected]> Cc: Andrey Ryabinin <[email protected]> Cc: Alexander Potapenko <[email protected]> Cc: Peter Collingbourne <[email protected]> Cc: Evgenii Stepanov <[email protected]> Cc: Branislav Rankov <[email protected]> Cc: Kevin Brodsky <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 037ecab commit 4748b6d

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

include/linux/mm.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1226,13 +1226,26 @@ static inline bool cpupid_match_pid(struct task_struct *task, int cpupid)
12261226
#endif /* CONFIG_NUMA_BALANCING */
12271227

12281228
#ifdef CONFIG_KASAN_SW_TAGS
1229+
1230+
/*
1231+
* KASAN per-page tags are stored xor'ed with 0xff. This allows to avoid
1232+
* setting tags for all pages to native kernel tag value 0xff, as the default
1233+
* value 0x00 maps to 0xff.
1234+
*/
1235+
12291236
static inline u8 page_kasan_tag(const struct page *page)
12301237
{
1231-
return (page->flags >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK;
1238+
u8 tag;
1239+
1240+
tag = (page->flags >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK;
1241+
tag ^= 0xff;
1242+
1243+
return tag;
12321244
}
12331245

12341246
static inline void page_kasan_tag_set(struct page *page, u8 tag)
12351247
{
1248+
tag ^= 0xff;
12361249
page->flags &= ~(KASAN_TAG_MASK << KASAN_TAG_PGSHIFT);
12371250
page->flags |= (tag & KASAN_TAG_MASK) << KASAN_TAG_PGSHIFT;
12381251
}

0 commit comments

Comments
 (0)