]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
kho: fix KASAN support for restored vmalloc regions
authorPasha Tatashin <pasha.tatashin@soleen.com>
Wed, 25 Feb 2026 22:38:57 +0000 (17:38 -0500)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 5 Apr 2026 20:53:06 +0000 (13:53 -0700)
Restored vmalloc regions are currently not properly marked for KASAN,
causing KASAN to treat accesses to these regions as out-of-bounds.

Fix this by properly unpoisoning the restored vmalloc area using
kasan_unpoison_vmalloc().  This requires setting the VM_UNINITIALIZED flag
during the initial area allocation and clearing it after the pages have
been mapped and unpoisoned, using the clear_vm_uninitialized_flag()
helper.

Link: https://lkml.kernel.org/r/20260225223857.1714801-3-pasha.tatashin@soleen.com
Fixes: a667300bd53f ("kho: add support for preserving vmalloc allocations")
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reported-by: Pratyush Yadav <pratyush@kernel.org>
Reviewed-by: Pratyush Yadav (Google) <pratyush@kernel.org>
Tested-by: Pratyush Yadav (Google) <pratyush@kernel.org>
Cc: Alexander Graf <graf@amazon.com>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: "Uladzislau Rezki (Sony)" <urezki@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
kernel/liveupdate/kexec_handover.c

index 410098bae0bff095d75bef9edd33500340e3d955..747a35107c84273f53ae2bd3a00895fdbdd8fc99 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/cma.h>
 #include <linux/kmemleak.h>
 #include <linux/count_zeros.h>
+#include <linux/kasan.h>
 #include <linux/kexec.h>
 #include <linux/kexec_handover.h>
 #include <linux/kho_radix_tree.h>
@@ -1077,6 +1078,7 @@ EXPORT_SYMBOL_GPL(kho_unpreserve_vmalloc);
 void *kho_restore_vmalloc(const struct kho_vmalloc *preservation)
 {
        struct kho_vmalloc_chunk *chunk = KHOSER_LOAD_PTR(preservation->first);
+       kasan_vmalloc_flags_t kasan_flags = KASAN_VMALLOC_PROT_NORMAL;
        unsigned int align, order, shift, vm_flags;
        unsigned long total_pages, contig_pages;
        unsigned long addr, size;
@@ -1128,7 +1130,8 @@ void *kho_restore_vmalloc(const struct kho_vmalloc *preservation)
                goto err_free_pages_array;
 
        area = __get_vm_area_node(total_pages * PAGE_SIZE, align, shift,
-                                 vm_flags, VMALLOC_START, VMALLOC_END,
+                                 vm_flags | VM_UNINITIALIZED,
+                                 VMALLOC_START, VMALLOC_END,
                                  NUMA_NO_NODE, GFP_KERNEL,
                                  __builtin_return_address(0));
        if (!area)
@@ -1143,6 +1146,13 @@ void *kho_restore_vmalloc(const struct kho_vmalloc *preservation)
        area->nr_pages = total_pages;
        area->pages = pages;
 
+       if (vm_flags & VM_ALLOC)
+               kasan_flags |= KASAN_VMALLOC_VM_ALLOC;
+
+       area->addr = kasan_unpoison_vmalloc(area->addr, total_pages * PAGE_SIZE,
+                                           kasan_flags);
+       clear_vm_uninitialized_flag(area);
+
        return area->addr;
 
 err_free_vm_area: