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