Message ID | 5cc1b789aad7c99cf4f3ec5b328b147ad53edb40.1544099024.git.andreyknvl@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | kasan: add software tag-based mode for arm64 | expand |
On Mon, Dec 10, 2018 at 2:35 AM Paul Gortmaker <paul.gortmaker@windriver.com> wrote: > > On Thu, Dec 6, 2018 at 7:25 AM Andrey Konovalov <andreyknvl@google.com> wrote: >> >> A tag-based KASAN shadow memory cell contains a memory tag, that >> corresponds to the tag in the top byte of the pointer, that points to that >> memory. The native top byte value of kernel pointers is 0xff, so with >> tag-based KASAN we need to initialize shadow memory to 0xff. >> >> Reviewed-by: Andrey Ryabinin <aryabinin@virtuozzo.com> >> Reviewed-by: Dmitry Vyukov <dvyukov@google.com> >> Signed-off-by: Andrey Konovalov <andreyknvl@google.com> >> --- >> arch/arm64/mm/kasan_init.c | 15 +++++++++++++-- >> include/linux/kasan.h | 8 ++++++++ > > > The version of this in linux-next breaks arm64 allmodconfig for me: > > mm/kasan/common.c: In function ‘kasan_module_alloc’: > mm/kasan/common.c:481:17: error: ‘KASAN_SHADOW_INIT’ undeclared (first use in this function) > __memset(ret, KASAN_SHADOW_INIT, shadow_size); > ^ > mm/kasan/common.c:481:17: note: each undeclared identifier is reported only once for each function it appears in > make[3]: *** [mm/kasan/common.o] Error 1 > make[3]: *** Waiting for unfinished jobs.... > make[2]: *** [mm/kasan] Error 2 > make[2]: *** Waiting for unfinished jobs.... > make[1]: *** [mm/] Error 2 > make: *** [sub-make] Error 2 Hi Paul, This is my bad, this should be fixed in v13 of this patchset, which is in mm right now but not in linux-next yet as it seems. Thanks! > > An automated git bisect-run points at this: > > 5c36287813721999e79ac76f637f1ba7e5054402 is the first bad commit > commit 5c36287813721999e79ac76f637f1ba7e5054402 > Author: Andrey Konovalov <andreyknvl@google.com> > Date: Wed Dec 5 11:13:21 2018 +1100 > > kasan: initialize shadow to 0xff for tag-based mode > > A quick look at the commit makes me think that the case where the > "# CONFIG_KASAN_GENERIC is not set" has not been handled. > > I'm using an older gcc 4.8.3 - only used for build testing. > > Paul. > -- > >> mm/kasan/common.c | 3 ++- >> 3 files changed, 23 insertions(+), 3 deletions(-) >> >> diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c >> index 4ebc19422931..7a4a0904cac8 100644 >> --- a/arch/arm64/mm/kasan_init.c >> +++ b/arch/arm64/mm/kasan_init.c >> @@ -43,6 +43,15 @@ static phys_addr_t __init kasan_alloc_zeroed_page(int node) >> return __pa(p); >> } >> >> +static phys_addr_t __init kasan_alloc_raw_page(int node) >> +{ >> + void *p = memblock_alloc_try_nid_raw(PAGE_SIZE, PAGE_SIZE, >> + __pa(MAX_DMA_ADDRESS), >> + MEMBLOCK_ALLOC_ACCESSIBLE, >> + node); >> + return __pa(p); >> +} >> + >> static pte_t *__init kasan_pte_offset(pmd_t *pmdp, unsigned long addr, int node, >> bool early) >> { >> @@ -92,7 +101,9 @@ static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr, >> do { >> phys_addr_t page_phys = early ? >> __pa_symbol(kasan_early_shadow_page) >> - : kasan_alloc_zeroed_page(node); >> + : kasan_alloc_raw_page(node); >> + if (!early) >> + memset(__va(page_phys), KASAN_SHADOW_INIT, PAGE_SIZE); >> next = addr + PAGE_SIZE; >> set_pte(ptep, pfn_pte(__phys_to_pfn(page_phys), PAGE_KERNEL)); >> } while (ptep++, addr = next, addr != end && pte_none(READ_ONCE(*ptep))); >> @@ -239,7 +250,7 @@ void __init kasan_init(void) >> pfn_pte(sym_to_pfn(kasan_early_shadow_page), >> PAGE_KERNEL_RO)); >> >> - memset(kasan_early_shadow_page, 0, PAGE_SIZE); >> + memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE); >> cpu_replace_ttbr1(lm_alias(swapper_pg_dir)); >> >> /* At this point kasan is fully initialized. Enable error messages */ >> diff --git a/include/linux/kasan.h b/include/linux/kasan.h >> index ec22d548d0d7..c56af24bd3e7 100644 >> --- a/include/linux/kasan.h >> +++ b/include/linux/kasan.h >> @@ -153,6 +153,8 @@ static inline size_t kasan_metadata_size(struct kmem_cache *cache) { return 0; } >> >> #ifdef CONFIG_KASAN_GENERIC >> >> +#define KASAN_SHADOW_INIT 0 >> + >> void kasan_cache_shrink(struct kmem_cache *cache); >> void kasan_cache_shutdown(struct kmem_cache *cache); >> >> @@ -163,4 +165,10 @@ static inline void kasan_cache_shutdown(struct kmem_cache *cache) {} >> >> #endif /* CONFIG_KASAN_GENERIC */ >> >> +#ifdef CONFIG_KASAN_SW_TAGS >> + >> +#define KASAN_SHADOW_INIT 0xFF >> + >> +#endif /* CONFIG_KASAN_SW_TAGS */ >> + >> #endif /* LINUX_KASAN_H */ >> diff --git a/mm/kasan/common.c b/mm/kasan/common.c >> index 5f68c93734ba..7134e75447ff 100644 >> --- a/mm/kasan/common.c >> +++ b/mm/kasan/common.c >> @@ -473,11 +473,12 @@ int kasan_module_alloc(void *addr, size_t size) >> >> ret = __vmalloc_node_range(shadow_size, 1, shadow_start, >> shadow_start + shadow_size, >> - GFP_KERNEL | __GFP_ZERO, >> + GFP_KERNEL, >> PAGE_KERNEL, VM_NO_GUARD, NUMA_NO_NODE, >> __builtin_return_address(0)); >> >> if (ret) { >> + __memset(ret, KASAN_SHADOW_INIT, shadow_size); >> find_vm_area(addr)->flags |= VM_KASAN; >> kmemleak_ignore(ret); >> return 0; >> -- >> 2.20.0.rc1.387.gf8505762e3-goog >>
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c index 4ebc19422931..7a4a0904cac8 100644 --- a/arch/arm64/mm/kasan_init.c +++ b/arch/arm64/mm/kasan_init.c @@ -43,6 +43,15 @@ static phys_addr_t __init kasan_alloc_zeroed_page(int node) return __pa(p); } +static phys_addr_t __init kasan_alloc_raw_page(int node) +{ + void *p = memblock_alloc_try_nid_raw(PAGE_SIZE, PAGE_SIZE, + __pa(MAX_DMA_ADDRESS), + MEMBLOCK_ALLOC_ACCESSIBLE, + node); + return __pa(p); +} + static pte_t *__init kasan_pte_offset(pmd_t *pmdp, unsigned long addr, int node, bool early) { @@ -92,7 +101,9 @@ static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr, do { phys_addr_t page_phys = early ? __pa_symbol(kasan_early_shadow_page) - : kasan_alloc_zeroed_page(node); + : kasan_alloc_raw_page(node); + if (!early) + memset(__va(page_phys), KASAN_SHADOW_INIT, PAGE_SIZE); next = addr + PAGE_SIZE; set_pte(ptep, pfn_pte(__phys_to_pfn(page_phys), PAGE_KERNEL)); } while (ptep++, addr = next, addr != end && pte_none(READ_ONCE(*ptep))); @@ -239,7 +250,7 @@ void __init kasan_init(void) pfn_pte(sym_to_pfn(kasan_early_shadow_page), PAGE_KERNEL_RO)); - memset(kasan_early_shadow_page, 0, PAGE_SIZE); + memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE); cpu_replace_ttbr1(lm_alias(swapper_pg_dir)); /* At this point kasan is fully initialized. Enable error messages */ diff --git a/include/linux/kasan.h b/include/linux/kasan.h index ec22d548d0d7..c56af24bd3e7 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -153,6 +153,8 @@ static inline size_t kasan_metadata_size(struct kmem_cache *cache) { return 0; } #ifdef CONFIG_KASAN_GENERIC +#define KASAN_SHADOW_INIT 0 + void kasan_cache_shrink(struct kmem_cache *cache); void kasan_cache_shutdown(struct kmem_cache *cache); @@ -163,4 +165,10 @@ static inline void kasan_cache_shutdown(struct kmem_cache *cache) {} #endif /* CONFIG_KASAN_GENERIC */ +#ifdef CONFIG_KASAN_SW_TAGS + +#define KASAN_SHADOW_INIT 0xFF + +#endif /* CONFIG_KASAN_SW_TAGS */ + #endif /* LINUX_KASAN_H */ diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 5f68c93734ba..7134e75447ff 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -473,11 +473,12 @@ int kasan_module_alloc(void *addr, size_t size) ret = __vmalloc_node_range(shadow_size, 1, shadow_start, shadow_start + shadow_size, - GFP_KERNEL | __GFP_ZERO, + GFP_KERNEL, PAGE_KERNEL, VM_NO_GUARD, NUMA_NO_NODE, __builtin_return_address(0)); if (ret) { + __memset(ret, KASAN_SHADOW_INIT, shadow_size); find_vm_area(addr)->flags |= VM_KASAN; kmemleak_ignore(ret); return 0;