Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kasan, page_alloc: allow skipping unpoisoning for HW_TAGS

Add a new GFP flag __GFP_SKIP_KASAN_UNPOISON that allows skipping KASAN
poisoning for page_alloc allocations. The flag is only effective with
HW_TAGS KASAN.

This flag will be used by vmalloc code for page_alloc allocations backing
vmalloc() mappings in a following patch. The reason to skip KASAN
poisoning for these pages in page_alloc is because vmalloc code will be
poisoning them instead.

Also reword the comment for __GFP_SKIP_KASAN_POISON.

Link: https://lkml.kernel.org/r/35c97d77a704f6ff971dd3bfe4be95855744108e.1643047180.git.andreyknvl@google.com
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Acked-by: Marco Elver <elver@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Evgenii Stepanov <eugenis@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Collingbourne <pcc@google.com>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Andrey Konovalov and committed by
Linus Torvalds
53ae233c f49d9c5b

+38 -19
+13 -8
include/linux/gfp.h
··· 55 55 #define ___GFP_ACCOUNT 0x400000u 56 56 #define ___GFP_ZEROTAGS 0x800000u 57 57 #ifdef CONFIG_KASAN_HW_TAGS 58 - #define ___GFP_SKIP_KASAN_POISON 0x1000000u 58 + #define ___GFP_SKIP_KASAN_UNPOISON 0x1000000u 59 + #define ___GFP_SKIP_KASAN_POISON 0x2000000u 59 60 #else 61 + #define ___GFP_SKIP_KASAN_UNPOISON 0 60 62 #define ___GFP_SKIP_KASAN_POISON 0 61 63 #endif 62 64 #ifdef CONFIG_LOCKDEP 63 - #define ___GFP_NOLOCKDEP 0x2000000u 65 + #define ___GFP_NOLOCKDEP 0x4000000u 64 66 #else 65 67 #define ___GFP_NOLOCKDEP 0 66 68 #endif ··· 243 241 * intended for optimization: setting memory tags at the same time as zeroing 244 242 * memory has minimal additional performace impact. 245 243 * 246 - * %__GFP_SKIP_KASAN_POISON returns a page which does not need to be poisoned 247 - * on deallocation. Typically used for userspace pages. Currently only has an 248 - * effect in HW tags mode. 244 + * %__GFP_SKIP_KASAN_UNPOISON makes KASAN skip unpoisoning on page allocation. 245 + * Only effective in HW_TAGS mode. 246 + * 247 + * %__GFP_SKIP_KASAN_POISON makes KASAN skip poisoning on page deallocation. 248 + * Typically, used for userspace pages. Only effective in HW_TAGS mode. 249 249 */ 250 250 #define __GFP_NOWARN ((__force gfp_t)___GFP_NOWARN) 251 251 #define __GFP_COMP ((__force gfp_t)___GFP_COMP) 252 252 #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) 253 253 #define __GFP_ZEROTAGS ((__force gfp_t)___GFP_ZEROTAGS) 254 - #define __GFP_SKIP_KASAN_POISON ((__force gfp_t)___GFP_SKIP_KASAN_POISON) 254 + #define __GFP_SKIP_KASAN_UNPOISON ((__force gfp_t)___GFP_SKIP_KASAN_UNPOISON) 255 + #define __GFP_SKIP_KASAN_POISON ((__force gfp_t)___GFP_SKIP_KASAN_POISON) 255 256 256 257 /* Disable lockdep for GFP context tracking */ 257 258 #define __GFP_NOLOCKDEP ((__force gfp_t)___GFP_NOLOCKDEP) 258 259 259 260 /* Room for N __GFP_FOO bits */ 260 - #define __GFP_BITS_SHIFT (24 + \ 261 - IS_ENABLED(CONFIG_KASAN_HW_TAGS) + \ 261 + #define __GFP_BITS_SHIFT (24 + \ 262 + 2 * IS_ENABLED(CONFIG_KASAN_HW_TAGS) + \ 262 263 IS_ENABLED(CONFIG_LOCKDEP)) 263 264 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) 264 265
+3 -2
include/trace/events/mmflags.h
··· 52 52 {(unsigned long)__GFP_ZEROTAGS, "__GFP_ZEROTAGS"} \ 53 53 54 54 #ifdef CONFIG_KASAN_HW_TAGS 55 - #define __def_gfpflag_names_kasan \ 56 - , {(unsigned long)__GFP_SKIP_KASAN_POISON, "__GFP_SKIP_KASAN_POISON"} 55 + #define __def_gfpflag_names_kasan , \ 56 + {(unsigned long)__GFP_SKIP_KASAN_POISON, "__GFP_SKIP_KASAN_POISON"}, \ 57 + {(unsigned long)__GFP_SKIP_KASAN_UNPOISON, "__GFP_SKIP_KASAN_UNPOISON"} 57 58 #else 58 59 #define __def_gfpflag_names_kasan 59 60 #endif
+22 -9
mm/page_alloc.c
··· 2343 2343 } 2344 2344 #endif /* CONFIG_DEBUG_VM */ 2345 2345 2346 + static inline bool should_skip_kasan_unpoison(gfp_t flags, bool init_tags) 2347 + { 2348 + /* Don't skip if a software KASAN mode is enabled. */ 2349 + if (IS_ENABLED(CONFIG_KASAN_GENERIC) || 2350 + IS_ENABLED(CONFIG_KASAN_SW_TAGS)) 2351 + return false; 2352 + 2353 + /* Skip, if hardware tag-based KASAN is not enabled. */ 2354 + if (!kasan_hw_tags_enabled()) 2355 + return true; 2356 + 2357 + /* 2358 + * With hardware tag-based KASAN enabled, skip if either: 2359 + * 2360 + * 1. Memory tags have already been cleared via tag_clear_highpage(). 2361 + * 2. Skipping has been requested via __GFP_SKIP_KASAN_UNPOISON. 2362 + */ 2363 + return init_tags || (flags & __GFP_SKIP_KASAN_UNPOISON); 2364 + } 2365 + 2346 2366 inline void post_alloc_hook(struct page *page, unsigned int order, 2347 2367 gfp_t gfp_flags) 2348 2368 { ··· 2402 2382 /* Note that memory is already initialized by the loop above. */ 2403 2383 init = false; 2404 2384 } 2405 - /* 2406 - * If either a software KASAN mode is enabled, or, 2407 - * in the case of hardware tag-based KASAN, 2408 - * if memory tags have not been cleared via tag_clear_highpage(). 2409 - */ 2410 - if (IS_ENABLED(CONFIG_KASAN_GENERIC) || 2411 - IS_ENABLED(CONFIG_KASAN_SW_TAGS) || 2412 - kasan_hw_tags_enabled() && !init_tags) { 2413 - /* Mark shadow memory or set memory tags. */ 2385 + if (!should_skip_kasan_unpoison(gfp_flags, init_tags)) { 2386 + /* Unpoison shadow memory or set memory tags. */ 2414 2387 kasan_unpoison_pages(page, order, init); 2415 2388 2416 2389 /* Note that memory is already initialized by KASAN. */