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

Configure Feed

Select the types of activity you want to include in your feed.

kasan: refactor pcpu kasan vmalloc unpoison

A KASAN tag mismatch, possibly causing a kernel panic, can be observed
on systems with a tag-based KASAN enabled and with multiple NUMA nodes.
It was reported on arm64 and reproduced on x86. It can be explained in
the following points:

1. There can be more than one virtual memory chunk.
2. Chunk's base address has a tag.
3. The base address points at the first chunk and thus inherits
the tag of the first chunk.
4. The subsequent chunks will be accessed with the tag from the
first chunk.
5. Thus, the subsequent chunks need to have their tag set to
match that of the first chunk.

Refactor code by reusing __kasan_unpoison_vmalloc in a new helper in
preparation for the actual fix.

Link: https://lkml.kernel.org/r/eb61d93b907e262eefcaa130261a08bcb6c5ce51.1764874575.git.m.wieczorretman@pm.me
Fixes: 1d96320f8d53 ("kasan, vmalloc: add vmalloc tagging for SW_TAGS")
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Jiayuan Chen <jiayuan.chen@linux.dev>
Cc: Kees Cook <kees@kernel.org>
Cc: Marco Elver <elver@google.com>
Cc: "Uladzislau Rezki (Sony)" <urezki@gmail.com>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: <stable@vger.kernel.org> [6.1+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Maciej Wieczor-Retman and committed by
Andrew Morton
6f13db03 007f5da4

+33 -3
+15
include/linux/kasan.h
··· 631 631 __kasan_poison_vmalloc(start, size); 632 632 } 633 633 634 + void __kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms, 635 + kasan_vmalloc_flags_t flags); 636 + static __always_inline void 637 + kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms, 638 + kasan_vmalloc_flags_t flags) 639 + { 640 + if (kasan_enabled()) 641 + __kasan_unpoison_vmap_areas(vms, nr_vms, flags); 642 + } 643 + 634 644 #else /* CONFIG_KASAN_VMALLOC */ 635 645 636 646 static inline void kasan_populate_early_vm_area_shadow(void *start, ··· 663 653 return (void *)start; 664 654 } 665 655 static inline void kasan_poison_vmalloc(const void *start, unsigned long size) 656 + { } 657 + 658 + static __always_inline void 659 + kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms, 660 + kasan_vmalloc_flags_t flags) 666 661 { } 667 662 668 663 #endif /* CONFIG_KASAN_VMALLOC */
+17
mm/kasan/common.c
··· 28 28 #include <linux/string.h> 29 29 #include <linux/types.h> 30 30 #include <linux/bug.h> 31 + #include <linux/vmalloc.h> 31 32 32 33 #include "kasan.h" 33 34 #include "../slab.h" ··· 576 575 } 577 576 return true; 578 577 } 578 + 579 + #ifdef CONFIG_KASAN_VMALLOC 580 + void __kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms, 581 + kasan_vmalloc_flags_t flags) 582 + { 583 + unsigned long size; 584 + void *addr; 585 + int area; 586 + 587 + for (area = 0 ; area < nr_vms ; area++) { 588 + size = vms[area]->size; 589 + addr = vms[area]->addr; 590 + vms[area]->addr = __kasan_unpoison_vmalloc(addr, size, flags); 591 + } 592 + } 593 + #endif
+1 -3
mm/vmalloc.c
··· 5027 5027 * With hardware tag-based KASAN, marking is skipped for 5028 5028 * non-VM_ALLOC mappings, see __kasan_unpoison_vmalloc(). 5029 5029 */ 5030 - for (area = 0; area < nr_vms; area++) 5031 - vms[area]->addr = kasan_unpoison_vmalloc(vms[area]->addr, 5032 - vms[area]->size, KASAN_VMALLOC_PROT_NORMAL); 5030 + kasan_unpoison_vmap_areas(vms, nr_vms, KASAN_VMALLOC_PROT_NORMAL); 5033 5031 5034 5032 kfree(vas); 5035 5033 return vms;