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

Merge branch 'for-next/mte' into for-next/core

KASAN optimisations for the hardware tagging (MTE) implementation.

* for-next/mte:
kasan: disable freed user page poisoning with HW tags
arm64: mte: handle tags zeroing at page allocation time
kasan: use separate (un)poison implementation for integrated init
mm: arch: remove indirection level in alloc_zeroed_user_highpage_movable()
kasan: speed up mte_set_mem_tag_range

+309 -135
+3 -3
arch/alpha/include/asm/page.h
··· 17 17 extern void clear_page(void *page); 18 18 #define clear_user_page(page, vaddr, pg) clear_page(page) 19 19 20 - #define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \ 21 - alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vmaddr) 22 - #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 20 + #define alloc_zeroed_user_highpage_movable(vma, vaddr) \ 21 + alloc_page_vma(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, vma, vmaddr) 22 + #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE_MOVABLE 23 23 24 24 extern void copy_page(void * _to, void * _from); 25 25 #define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
+67 -26
arch/arm64/include/asm/mte-kasan.h
··· 48 48 return mte_get_ptr_tag(addr); 49 49 } 50 50 51 + static inline u64 __stg_post(u64 p) 52 + { 53 + asm volatile(__MTE_PREAMBLE "stg %0, [%0], #16" 54 + : "+r"(p) 55 + : 56 + : "memory"); 57 + return p; 58 + } 59 + 60 + static inline u64 __stzg_post(u64 p) 61 + { 62 + asm volatile(__MTE_PREAMBLE "stzg %0, [%0], #16" 63 + : "+r"(p) 64 + : 65 + : "memory"); 66 + return p; 67 + } 68 + 69 + static inline void __dc_gva(u64 p) 70 + { 71 + asm volatile(__MTE_PREAMBLE "dc gva, %0" : : "r"(p) : "memory"); 72 + } 73 + 74 + static inline void __dc_gzva(u64 p) 75 + { 76 + asm volatile(__MTE_PREAMBLE "dc gzva, %0" : : "r"(p) : "memory"); 77 + } 78 + 51 79 /* 52 80 * Assign allocation tags for a region of memory based on the pointer tag. 53 81 * Note: The address must be non-NULL and MTE_GRANULE_SIZE aligned and 54 - * size must be non-zero and MTE_GRANULE_SIZE aligned. 82 + * size must be MTE_GRANULE_SIZE aligned. 55 83 */ 56 - static inline void mte_set_mem_tag_range(void *addr, size_t size, 57 - u8 tag, bool init) 84 + static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag, 85 + bool init) 58 86 { 59 - u64 curr, end; 87 + u64 curr, mask, dczid_bs, end1, end2, end3; 60 88 61 - if (!size) 62 - return; 89 + /* Read DC G(Z)VA block size from the system register. */ 90 + dczid_bs = 4ul << (read_cpuid(DCZID_EL0) & 0xf); 63 91 64 92 curr = (u64)__tag_set(addr, tag); 65 - end = curr + size; 93 + mask = dczid_bs - 1; 94 + /* STG/STZG up to the end of the first block. */ 95 + end1 = curr | mask; 96 + end3 = curr + size; 97 + /* DC GVA / GZVA in [end1, end2) */ 98 + end2 = end3 & ~mask; 66 99 67 100 /* 68 - * 'asm volatile' is required to prevent the compiler to move 69 - * the statement outside of the loop. 101 + * The following code uses STG on the first DC GVA block even if the 102 + * start address is aligned - it appears to be faster than an alignment 103 + * check + conditional branch. Also, if the range size is at least 2 DC 104 + * GVA blocks, the first two loops can use post-condition to save one 105 + * branch each. 70 106 */ 71 - if (init) { 72 - do { 73 - asm volatile(__MTE_PREAMBLE "stzg %0, [%0]" 74 - : 75 - : "r" (curr) 76 - : "memory"); 77 - curr += MTE_GRANULE_SIZE; 78 - } while (curr != end); 79 - } else { 80 - do { 81 - asm volatile(__MTE_PREAMBLE "stg %0, [%0]" 82 - : 83 - : "r" (curr) 84 - : "memory"); 85 - curr += MTE_GRANULE_SIZE; 86 - } while (curr != end); 87 - } 107 + #define SET_MEMTAG_RANGE(stg_post, dc_gva) \ 108 + do { \ 109 + if (size >= 2 * dczid_bs) { \ 110 + do { \ 111 + curr = stg_post(curr); \ 112 + } while (curr < end1); \ 113 + \ 114 + do { \ 115 + dc_gva(curr); \ 116 + curr += dczid_bs; \ 117 + } while (curr < end2); \ 118 + } \ 119 + \ 120 + while (curr < end3) \ 121 + curr = stg_post(curr); \ 122 + } while (0) 123 + 124 + if (init) 125 + SET_MEMTAG_RANGE(__stzg_post, __dc_gzva); 126 + else 127 + SET_MEMTAG_RANGE(__stg_post, __dc_gva); 128 + #undef SET_MEMTAG_RANGE 88 129 } 89 130 90 131 void mte_enable_kernel_sync(void);
+4
arch/arm64/include/asm/mte.h
··· 37 37 /* track which pages have valid allocation tags */ 38 38 #define PG_mte_tagged PG_arch_2 39 39 40 + void mte_zero_clear_page_tags(void *addr); 40 41 void mte_sync_tags(pte_t *ptep, pte_t pte); 41 42 void mte_copy_page_tags(void *kto, const void *kfrom); 42 43 void mte_thread_init_user(void); ··· 54 53 /* unused if !CONFIG_ARM64_MTE, silence the compiler */ 55 54 #define PG_mte_tagged 0 56 55 56 + static inline void mte_zero_clear_page_tags(void *addr) 57 + { 58 + } 57 59 static inline void mte_sync_tags(pte_t *ptep, pte_t pte) 58 60 { 59 61 }
+7 -3
arch/arm64/include/asm/page.h
··· 13 13 #ifndef __ASSEMBLY__ 14 14 15 15 #include <linux/personality.h> /* for READ_IMPLIES_EXEC */ 16 + #include <linux/types.h> /* for gfp_t */ 16 17 #include <asm/pgtable-types.h> 17 18 18 19 struct page; ··· 29 28 void copy_highpage(struct page *to, struct page *from); 30 29 #define __HAVE_ARCH_COPY_HIGHPAGE 31 30 32 - #define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \ 33 - alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr) 34 - #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 31 + struct page *alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma, 32 + unsigned long vaddr); 33 + #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE_MOVABLE 34 + 35 + void tag_clear_highpage(struct page *to); 36 + #define __HAVE_ARCH_TAG_CLEAR_HIGHPAGE 35 37 36 38 #define clear_user_page(page, vaddr, pg) clear_page(page) 37 39 #define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
+20
arch/arm64/lib/mte.S
··· 37 37 SYM_FUNC_END(mte_clear_page_tags) 38 38 39 39 /* 40 + * Zero the page and tags at the same time 41 + * 42 + * Parameters: 43 + * x0 - address to the beginning of the page 44 + */ 45 + SYM_FUNC_START(mte_zero_clear_page_tags) 46 + mrs x1, dczid_el0 47 + and w1, w1, #0xf 48 + mov x2, #4 49 + lsl x1, x2, x1 50 + and x0, x0, #(1 << MTE_TAG_SHIFT) - 1 // clear the tag 51 + 52 + 1: dc gzva, x0 53 + add x0, x0, x1 54 + tst x0, #(PAGE_SIZE - 1) 55 + b.ne 1b 56 + ret 57 + SYM_FUNC_END(mte_zero_clear_page_tags) 58 + 59 + /* 40 60 * Copy the tags from the source page to the destination one 41 61 * x0 - address of the destination page 42 62 * x1 - address of the source page
+26
arch/arm64/mm/fault.c
··· 919 919 debug_exception_exit(regs); 920 920 } 921 921 NOKPROBE_SYMBOL(do_debug_exception); 922 + 923 + /* 924 + * Used during anonymous page fault handling. 925 + */ 926 + struct page *alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma, 927 + unsigned long vaddr) 928 + { 929 + gfp_t flags = GFP_HIGHUSER_MOVABLE | __GFP_ZERO; 930 + 931 + /* 932 + * If the page is mapped with PROT_MTE, initialise the tags at the 933 + * point of allocation and page zeroing as this is usually faster than 934 + * separate DC ZVA and STGM. 935 + */ 936 + if (vma->vm_flags & VM_MTE) 937 + flags |= __GFP_ZEROTAGS; 938 + 939 + return alloc_page_vma(flags, vma, vaddr); 940 + } 941 + 942 + void tag_clear_highpage(struct page *page) 943 + { 944 + mte_zero_clear_page_tags(page_address(page)); 945 + page_kasan_tag_reset(page); 946 + set_bit(PG_mte_tagged, &page->flags); 947 + }
+7 -3
arch/arm64/mm/proc.S
··· 46 46 #endif 47 47 48 48 #ifdef CONFIG_KASAN_HW_TAGS 49 - #define TCR_KASAN_HW_FLAGS SYS_TCR_EL1_TCMA1 | TCR_TBI1 | TCR_TBID1 49 + #define TCR_MTE_FLAGS SYS_TCR_EL1_TCMA1 | TCR_TBI1 | TCR_TBID1 50 50 #else 51 - #define TCR_KASAN_HW_FLAGS 0 51 + /* 52 + * The mte_zero_clear_page_tags() implementation uses DC GZVA, which relies on 53 + * TBI being enabled at EL1. 54 + */ 55 + #define TCR_MTE_FLAGS TCR_TBI1 | TCR_TBID1 52 56 #endif 53 57 54 58 /* ··· 458 454 msr_s SYS_TFSRE0_EL1, xzr 459 455 460 456 /* set the TCR_EL1 bits */ 461 - mov_q x10, TCR_KASAN_HW_FLAGS 457 + mov_q x10, TCR_MTE_FLAGS 462 458 orr tcr, tcr, x10 463 459 1: 464 460 #endif
+3 -3
arch/ia64/include/asm/page.h
··· 82 82 } while (0) 83 83 84 84 85 - #define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \ 85 + #define alloc_zeroed_user_highpage_movable(vma, vaddr) \ 86 86 ({ \ 87 87 struct page *page = alloc_page_vma( \ 88 - GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr); \ 88 + GFP_HIGHUSER_MOVABLE | __GFP_ZERO, vma, vaddr); \ 89 89 if (page) \ 90 90 flush_dcache_page(page); \ 91 91 page; \ 92 92 }) 93 93 94 - #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 94 + #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE_MOVABLE 95 95 96 96 #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) 97 97
+3 -3
arch/m68k/include/asm/page_no.h
··· 13 13 #define clear_user_page(page, vaddr, pg) clear_page(page) 14 14 #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) 15 15 16 - #define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \ 17 - alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr) 18 - #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 16 + #define alloc_zeroed_user_highpage_movable(vma, vaddr) \ 17 + alloc_page_vma(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, vma, vaddr) 18 + #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE_MOVABLE 19 19 20 20 #define __pa(vaddr) ((unsigned long)(vaddr)) 21 21 #define __va(paddr) ((void *)((unsigned long)(paddr)))
+3 -3
arch/s390/include/asm/page.h
··· 68 68 #define clear_user_page(page, vaddr, pg) clear_page(page) 69 69 #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) 70 70 71 - #define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \ 72 - alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr) 73 - #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 71 + #define alloc_zeroed_user_highpage_movable(vma, vaddr) \ 72 + alloc_page_vma(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, vma, vaddr) 73 + #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE_MOVABLE 74 74 75 75 /* 76 76 * These are used to make use of C type-checking..
+3 -3
arch/x86/include/asm/page.h
··· 34 34 copy_page(to, from); 35 35 } 36 36 37 - #define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \ 38 - alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr) 39 - #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 37 + #define alloc_zeroed_user_highpage_movable(vma, vaddr) \ 38 + alloc_page_vma(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, vma, vaddr) 39 + #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE_MOVABLE 40 40 41 41 #ifndef __pa 42 42 #define __pa(x) __phys_addr((unsigned long)(x))
+15 -3
include/linux/gfp.h
··· 53 53 #define ___GFP_HARDWALL 0x100000u 54 54 #define ___GFP_THISNODE 0x200000u 55 55 #define ___GFP_ACCOUNT 0x400000u 56 + #define ___GFP_ZEROTAGS 0x800000u 57 + #define ___GFP_SKIP_KASAN_POISON 0x1000000u 56 58 #ifdef CONFIG_LOCKDEP 57 - #define ___GFP_NOLOCKDEP 0x800000u 59 + #define ___GFP_NOLOCKDEP 0x2000000u 58 60 #else 59 61 #define ___GFP_NOLOCKDEP 0 60 62 #endif ··· 231 229 * %__GFP_COMP address compound page metadata. 232 230 * 233 231 * %__GFP_ZERO returns a zeroed page on success. 232 + * 233 + * %__GFP_ZEROTAGS returns a page with zeroed memory tags on success, if 234 + * __GFP_ZERO is set. 235 + * 236 + * %__GFP_SKIP_KASAN_POISON returns a page which does not need to be poisoned 237 + * on deallocation. Typically used for userspace pages. Currently only has an 238 + * effect in HW tags mode. 234 239 */ 235 240 #define __GFP_NOWARN ((__force gfp_t)___GFP_NOWARN) 236 241 #define __GFP_COMP ((__force gfp_t)___GFP_COMP) 237 242 #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) 243 + #define __GFP_ZEROTAGS ((__force gfp_t)___GFP_ZEROTAGS) 244 + #define __GFP_SKIP_KASAN_POISON ((__force gfp_t)___GFP_SKIP_KASAN_POISON) 238 245 239 246 /* Disable lockdep for GFP context tracking */ 240 247 #define __GFP_NOLOCKDEP ((__force gfp_t)___GFP_NOLOCKDEP) 241 248 242 249 /* Room for N __GFP_FOO bits */ 243 - #define __GFP_BITS_SHIFT (23 + IS_ENABLED(CONFIG_LOCKDEP)) 250 + #define __GFP_BITS_SHIFT (25 + IS_ENABLED(CONFIG_LOCKDEP)) 244 251 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) 245 252 246 253 /** ··· 330 319 #define GFP_DMA __GFP_DMA 331 320 #define GFP_DMA32 __GFP_DMA32 332 321 #define GFP_HIGHUSER (GFP_USER | __GFP_HIGHMEM) 333 - #define GFP_HIGHUSER_MOVABLE (GFP_HIGHUSER | __GFP_MOVABLE) 322 + #define GFP_HIGHUSER_MOVABLE (GFP_HIGHUSER | __GFP_MOVABLE | \ 323 + __GFP_SKIP_KASAN_POISON) 334 324 #define GFP_TRANSHUGE_LIGHT ((GFP_HIGHUSER_MOVABLE | __GFP_COMP | \ 335 325 __GFP_NOMEMALLOC | __GFP_NOWARN) & ~__GFP_RECLAIM) 336 326 #define GFP_TRANSHUGE (GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)
+16 -27
include/linux/highmem.h
··· 152 152 } 153 153 #endif 154 154 155 - #ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 155 + #ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE_MOVABLE 156 156 /** 157 - * __alloc_zeroed_user_highpage - Allocate a zeroed HIGHMEM page for a VMA with caller-specified movable GFP flags 158 - * @movableflags: The GFP flags related to the pages future ability to move like __GFP_MOVABLE 157 + * alloc_zeroed_user_highpage_movable - Allocate a zeroed HIGHMEM page for a VMA that the caller knows can move 159 158 * @vma: The VMA the page is to be allocated for 160 159 * @vaddr: The virtual address the page will be inserted into 161 160 * 162 - * This function will allocate a page for a VMA but the caller is expected 163 - * to specify via movableflags whether the page will be movable in the 164 - * future or not 161 + * This function will allocate a page for a VMA that the caller knows will 162 + * be able to migrate in the future using move_pages() or reclaimed 165 163 * 166 164 * An architecture may override this function by defining 167 - * __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE and providing their own 165 + * __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE_MOVABLE and providing their own 168 166 * implementation. 169 167 */ 170 168 static inline struct page * 171 - __alloc_zeroed_user_highpage(gfp_t movableflags, 172 - struct vm_area_struct *vma, 173 - unsigned long vaddr) 169 + alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma, 170 + unsigned long vaddr) 174 171 { 175 - struct page *page = alloc_page_vma(GFP_HIGHUSER | movableflags, 176 - vma, vaddr); 172 + struct page *page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); 177 173 178 174 if (page) 179 175 clear_user_highpage(page, vaddr); ··· 178 182 } 179 183 #endif 180 184 181 - /** 182 - * alloc_zeroed_user_highpage_movable - Allocate a zeroed HIGHMEM page for a VMA that the caller knows can move 183 - * @vma: The VMA the page is to be allocated for 184 - * @vaddr: The virtual address the page will be inserted into 185 - * 186 - * This function will allocate a page for a VMA that the caller knows will 187 - * be able to migrate in the future using move_pages() or reclaimed 188 - */ 189 - static inline struct page * 190 - alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma, 191 - unsigned long vaddr) 192 - { 193 - return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr); 194 - } 195 - 196 185 static inline void clear_highpage(struct page *page) 197 186 { 198 187 void *kaddr = kmap_atomic(page); 199 188 clear_page(kaddr); 200 189 kunmap_atomic(kaddr); 201 190 } 191 + 192 + #ifndef __HAVE_ARCH_TAG_CLEAR_HIGHPAGE 193 + 194 + static inline void tag_clear_highpage(struct page *page) 195 + { 196 + } 197 + 198 + #endif 202 199 203 200 /* 204 201 * If we pass in a base or tail page, we can zero up to PAGE_SIZE.
+38 -26
include/linux/kasan.h
··· 2 2 #ifndef _LINUX_KASAN_H 3 3 #define _LINUX_KASAN_H 4 4 5 + #include <linux/bug.h> 5 6 #include <linux/static_key.h> 6 7 #include <linux/types.h> 7 8 ··· 80 79 81 80 #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */ 82 81 83 - #ifdef CONFIG_KASAN 84 - 85 - struct kasan_cache { 86 - int alloc_meta_offset; 87 - int free_meta_offset; 88 - bool is_kmalloc; 89 - }; 90 - 91 82 #ifdef CONFIG_KASAN_HW_TAGS 92 83 93 84 DECLARE_STATIC_KEY_FALSE(kasan_flag_enabled); ··· 94 101 return kasan_enabled(); 95 102 } 96 103 104 + void kasan_alloc_pages(struct page *page, unsigned int order, gfp_t flags); 105 + void kasan_free_pages(struct page *page, unsigned int order); 106 + 97 107 #else /* CONFIG_KASAN_HW_TAGS */ 98 108 99 109 static inline bool kasan_enabled(void) 100 110 { 101 - return true; 111 + return IS_ENABLED(CONFIG_KASAN); 102 112 } 103 113 104 114 static inline bool kasan_has_integrated_init(void) ··· 109 113 return false; 110 114 } 111 115 116 + static __always_inline void kasan_alloc_pages(struct page *page, 117 + unsigned int order, gfp_t flags) 118 + { 119 + /* Only available for integrated init. */ 120 + BUILD_BUG(); 121 + } 122 + 123 + static __always_inline void kasan_free_pages(struct page *page, 124 + unsigned int order) 125 + { 126 + /* Only available for integrated init. */ 127 + BUILD_BUG(); 128 + } 129 + 112 130 #endif /* CONFIG_KASAN_HW_TAGS */ 131 + 132 + #ifdef CONFIG_KASAN 133 + 134 + struct kasan_cache { 135 + int alloc_meta_offset; 136 + int free_meta_offset; 137 + bool is_kmalloc; 138 + }; 113 139 114 140 slab_flags_t __kasan_never_merge(void); 115 141 static __always_inline slab_flags_t kasan_never_merge(void) ··· 148 130 __kasan_unpoison_range(addr, size); 149 131 } 150 132 151 - void __kasan_alloc_pages(struct page *page, unsigned int order, bool init); 152 - static __always_inline void kasan_alloc_pages(struct page *page, 133 + void __kasan_poison_pages(struct page *page, unsigned int order, bool init); 134 + static __always_inline void kasan_poison_pages(struct page *page, 153 135 unsigned int order, bool init) 154 136 { 155 137 if (kasan_enabled()) 156 - __kasan_alloc_pages(page, order, init); 138 + __kasan_poison_pages(page, order, init); 157 139 } 158 140 159 - void __kasan_free_pages(struct page *page, unsigned int order, bool init); 160 - static __always_inline void kasan_free_pages(struct page *page, 161 - unsigned int order, bool init) 141 + void __kasan_unpoison_pages(struct page *page, unsigned int order, bool init); 142 + static __always_inline void kasan_unpoison_pages(struct page *page, 143 + unsigned int order, bool init) 162 144 { 163 145 if (kasan_enabled()) 164 - __kasan_free_pages(page, order, init); 146 + __kasan_unpoison_pages(page, order, init); 165 147 } 166 148 167 149 void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size, ··· 303 285 304 286 #else /* CONFIG_KASAN */ 305 287 306 - static inline bool kasan_enabled(void) 307 - { 308 - return false; 309 - } 310 - static inline bool kasan_has_integrated_init(void) 311 - { 312 - return false; 313 - } 314 288 static inline slab_flags_t kasan_never_merge(void) 315 289 { 316 290 return 0; 317 291 } 318 292 static inline void kasan_unpoison_range(const void *address, size_t size) {} 319 - static inline void kasan_alloc_pages(struct page *page, unsigned int order, bool init) {} 320 - static inline void kasan_free_pages(struct page *page, unsigned int order, bool init) {} 293 + static inline void kasan_poison_pages(struct page *page, unsigned int order, 294 + bool init) {} 295 + static inline void kasan_unpoison_pages(struct page *page, unsigned int order, 296 + bool init) {} 321 297 static inline void kasan_cache_create(struct kmem_cache *cache, 322 298 unsigned int *size, 323 299 slab_flags_t *flags) {}
+9
include/linux/page-flags.h
··· 138 138 #ifdef CONFIG_64BIT 139 139 PG_arch_2, 140 140 #endif 141 + #ifdef CONFIG_KASAN_HW_TAGS 142 + PG_skip_kasan_poison, 143 + #endif 141 144 __NR_PAGEFLAGS, 142 145 143 146 /* Filesystems */ ··· 444 441 SETPAGEFLAG(Young, young, PF_ANY) 445 442 TESTCLEARFLAG(Young, young, PF_ANY) 446 443 PAGEFLAG(Idle, idle, PF_ANY) 444 + #endif 445 + 446 + #ifdef CONFIG_KASAN_HW_TAGS 447 + PAGEFLAG(SkipKASanPoison, skip_kasan_poison, PF_HEAD) 448 + #else 449 + PAGEFLAG_FALSE(SkipKASanPoison) 447 450 #endif 448 451 449 452 /*
+8 -1
include/trace/events/mmflags.h
··· 85 85 #define IF_HAVE_PG_ARCH_2(flag,string) 86 86 #endif 87 87 88 + #ifdef CONFIG_KASAN_HW_TAGS 89 + #define IF_HAVE_PG_SKIP_KASAN_POISON(flag,string) ,{1UL << flag, string} 90 + #else 91 + #define IF_HAVE_PG_SKIP_KASAN_POISON(flag,string) 92 + #endif 93 + 88 94 #define __def_pageflag_names \ 89 95 {1UL << PG_locked, "locked" }, \ 90 96 {1UL << PG_waiters, "waiters" }, \ ··· 118 112 IF_HAVE_PG_HWPOISON(PG_hwpoison, "hwpoison" ) \ 119 113 IF_HAVE_PG_IDLE(PG_young, "young" ) \ 120 114 IF_HAVE_PG_IDLE(PG_idle, "idle" ) \ 121 - IF_HAVE_PG_ARCH_2(PG_arch_2, "arch_2" ) 115 + IF_HAVE_PG_ARCH_2(PG_arch_2, "arch_2" ) \ 116 + IF_HAVE_PG_SKIP_KASAN_POISON(PG_skip_kasan_poison, "skip_kasan_poison") 122 117 123 118 #define show_page_flags(flags) \ 124 119 (flags) ? __print_flags(flags, "|", \
+2 -2
mm/kasan/common.c
··· 97 97 return 0; 98 98 } 99 99 100 - void __kasan_alloc_pages(struct page *page, unsigned int order, bool init) 100 + void __kasan_unpoison_pages(struct page *page, unsigned int order, bool init) 101 101 { 102 102 u8 tag; 103 103 unsigned long i; ··· 111 111 kasan_unpoison(page_address(page), PAGE_SIZE << order, init); 112 112 } 113 113 114 - void __kasan_free_pages(struct page *page, unsigned int order, bool init) 114 + void __kasan_poison_pages(struct page *page, unsigned int order, bool init) 115 115 { 116 116 if (likely(!PageHighMem(page))) 117 117 kasan_poison(page_address(page), PAGE_SIZE << order,
+32
mm/kasan/hw_tags.c
··· 238 238 return &alloc_meta->free_track[0]; 239 239 } 240 240 241 + void kasan_alloc_pages(struct page *page, unsigned int order, gfp_t flags) 242 + { 243 + /* 244 + * This condition should match the one in post_alloc_hook() in 245 + * page_alloc.c. 246 + */ 247 + bool init = !want_init_on_free() && want_init_on_alloc(flags); 248 + 249 + if (flags & __GFP_SKIP_KASAN_POISON) 250 + SetPageSkipKASanPoison(page); 251 + 252 + if (flags & __GFP_ZEROTAGS) { 253 + int i; 254 + 255 + for (i = 0; i != 1 << order; ++i) 256 + tag_clear_highpage(page + i); 257 + } else { 258 + kasan_unpoison_pages(page, order, init); 259 + } 260 + } 261 + 262 + void kasan_free_pages(struct page *page, unsigned int order) 263 + { 264 + /* 265 + * This condition should match the one in free_pages_prepare() in 266 + * page_alloc.c. 267 + */ 268 + bool init = want_init_on_free(); 269 + 270 + kasan_poison_pages(page, order, init); 271 + } 272 + 241 273 #if IS_ENABLED(CONFIG_KASAN_KUNIT_TEST) 242 274 243 275 void kasan_set_tagging_report_once(bool state)
+4 -2
mm/mempool.c
··· 106 106 if (pool->alloc == mempool_alloc_slab || pool->alloc == mempool_kmalloc) 107 107 kasan_slab_free_mempool(element); 108 108 else if (pool->alloc == mempool_alloc_pages) 109 - kasan_free_pages(element, (unsigned long)pool->pool_data, false); 109 + kasan_poison_pages(element, (unsigned long)pool->pool_data, 110 + false); 110 111 } 111 112 112 113 static void kasan_unpoison_element(mempool_t *pool, void *element) ··· 115 114 if (pool->alloc == mempool_alloc_slab || pool->alloc == mempool_kmalloc) 116 115 kasan_unpoison_range(element, __ksize(element)); 117 116 else if (pool->alloc == mempool_alloc_pages) 118 - kasan_alloc_pages(element, (unsigned long)pool->pool_data, false); 117 + kasan_unpoison_pages(element, (unsigned long)pool->pool_data, 118 + false); 119 119 } 120 120 121 121 static __always_inline void add_element(mempool_t *pool, void *element)
+39 -27
mm/page_alloc.c
··· 382 382 static DEFINE_STATIC_KEY_TRUE(deferred_pages); 383 383 384 384 /* 385 - * Calling kasan_free_pages() only after deferred memory initialization 385 + * Calling kasan_poison_pages() only after deferred memory initialization 386 386 * has completed. Poisoning pages during deferred memory init will greatly 387 387 * lengthen the process and cause problem in large memory systems as the 388 388 * deferred pages initialization is done with interrupt disabled. ··· 394 394 * on-demand allocation and then freed again before the deferred pages 395 395 * initialization is done, but this is not likely to happen. 396 396 */ 397 - static inline void kasan_free_nondeferred_pages(struct page *page, int order, 398 - bool init, fpi_t fpi_flags) 397 + static inline bool should_skip_kasan_poison(struct page *page, fpi_t fpi_flags) 399 398 { 400 - if (static_branch_unlikely(&deferred_pages)) 401 - return; 402 - if (!IS_ENABLED(CONFIG_KASAN_GENERIC) && 403 - (fpi_flags & FPI_SKIP_KASAN_POISON)) 404 - return; 405 - kasan_free_pages(page, order, init); 399 + return static_branch_unlikely(&deferred_pages) || 400 + (!IS_ENABLED(CONFIG_KASAN_GENERIC) && 401 + (fpi_flags & FPI_SKIP_KASAN_POISON)) || 402 + PageSkipKASanPoison(page); 406 403 } 407 404 408 405 /* Returns true if the struct page for the pfn is uninitialised */ ··· 450 453 return false; 451 454 } 452 455 #else 453 - static inline void kasan_free_nondeferred_pages(struct page *page, int order, 454 - bool init, fpi_t fpi_flags) 456 + static inline bool should_skip_kasan_poison(struct page *page, fpi_t fpi_flags) 455 457 { 456 - if (!IS_ENABLED(CONFIG_KASAN_GENERIC) && 457 - (fpi_flags & FPI_SKIP_KASAN_POISON)) 458 - return; 459 - kasan_free_pages(page, order, init); 458 + return (!IS_ENABLED(CONFIG_KASAN_GENERIC) && 459 + (fpi_flags & FPI_SKIP_KASAN_POISON)) || 460 + PageSkipKASanPoison(page); 460 461 } 461 462 462 463 static inline bool early_page_uninitialised(unsigned long pfn) ··· 1221 1226 return ret; 1222 1227 } 1223 1228 1224 - static void kernel_init_free_pages(struct page *page, int numpages) 1229 + static void kernel_init_free_pages(struct page *page, int numpages, bool zero_tags) 1225 1230 { 1226 1231 int i; 1232 + 1233 + if (zero_tags) { 1234 + for (i = 0; i < numpages; i++) 1235 + tag_clear_highpage(page + i); 1236 + return; 1237 + } 1227 1238 1228 1239 /* s390's use of memset() could override KASAN redzones. */ 1229 1240 kasan_disable_current(); ··· 1246 1245 unsigned int order, bool check_free, fpi_t fpi_flags) 1247 1246 { 1248 1247 int bad = 0; 1249 - bool init; 1248 + bool skip_kasan_poison = should_skip_kasan_poison(page, fpi_flags); 1250 1249 1251 1250 VM_BUG_ON_PAGE(PageTail(page), page); 1252 1251 ··· 1315 1314 * With hardware tag-based KASAN, memory tags must be set before the 1316 1315 * page becomes unavailable via debug_pagealloc or arch_free_page. 1317 1316 */ 1318 - init = want_init_on_free(); 1319 - if (init && !kasan_has_integrated_init()) 1320 - kernel_init_free_pages(page, 1 << order); 1321 - kasan_free_nondeferred_pages(page, order, init, fpi_flags); 1317 + if (kasan_has_integrated_init()) { 1318 + if (!skip_kasan_poison) 1319 + kasan_free_pages(page, order); 1320 + } else { 1321 + bool init = want_init_on_free(); 1322 + 1323 + if (init) 1324 + kernel_init_free_pages(page, 1 << order, false); 1325 + if (!skip_kasan_poison) 1326 + kasan_poison_pages(page, order, init); 1327 + } 1322 1328 1323 1329 /* 1324 1330 * arch_free_page() can make the page's contents inaccessible. s390 ··· 2332 2324 inline void post_alloc_hook(struct page *page, unsigned int order, 2333 2325 gfp_t gfp_flags) 2334 2326 { 2335 - bool init; 2336 - 2337 2327 set_page_private(page, 0); 2338 2328 set_page_refcounted(page); 2339 2329 ··· 2350 2344 * kasan_alloc_pages and kernel_init_free_pages must be 2351 2345 * kept together to avoid discrepancies in behavior. 2352 2346 */ 2353 - init = !want_init_on_free() && want_init_on_alloc(gfp_flags); 2354 - kasan_alloc_pages(page, order, init); 2355 - if (init && !kasan_has_integrated_init()) 2356 - kernel_init_free_pages(page, 1 << order); 2347 + if (kasan_has_integrated_init()) { 2348 + kasan_alloc_pages(page, order, gfp_flags); 2349 + } else { 2350 + bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags); 2351 + 2352 + kasan_unpoison_pages(page, order, init); 2353 + if (init) 2354 + kernel_init_free_pages(page, 1 << order, 2355 + gfp_flags & __GFP_ZEROTAGS); 2356 + } 2357 2357 2358 2358 set_page_owner(page, order, gfp_flags); 2359 2359 }