Commit 4aff1dc4 authored by Andrey Konovalov's avatar Andrey Konovalov Committed by Linus Torvalds

kasan, vmalloc: reset tags in vmalloc functions

In preparation for adding vmalloc support to SW/HW_TAGS KASAN, reset
pointer tags in functions that use pointer values in range checks.

vread() is a special case here.  Despite the untagging of the addr pointer
in its prologue, the accesses performed by vread() are checked.

Instead of accessing the virtual mappings though addr directly, vread()
recovers the physical address via page_address(vmalloc_to_page()) and
acceses that.  And as page_address() recovers the pointer tag, the
accesses get checked.

Link: https://lkml.kernel.org/r/046003c5f683cacb0ba18e1079e9688bb3dca943.1643047180.git.andreyknvl@google.comSigned-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Acked-by: default avatarMarco Elver <elver@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Evgenii Stepanov <eugenis@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Collingbourne <pcc@google.com>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 579fb0ac
...@@ -74,7 +74,7 @@ static const bool vmap_allow_huge = false; ...@@ -74,7 +74,7 @@ static const bool vmap_allow_huge = false;
bool is_vmalloc_addr(const void *x) bool is_vmalloc_addr(const void *x)
{ {
unsigned long addr = (unsigned long)x; unsigned long addr = (unsigned long)kasan_reset_tag(x);
return addr >= VMALLOC_START && addr < VMALLOC_END; return addr >= VMALLOC_START && addr < VMALLOC_END;
} }
...@@ -631,7 +631,7 @@ int is_vmalloc_or_module_addr(const void *x) ...@@ -631,7 +631,7 @@ int is_vmalloc_or_module_addr(const void *x)
* just put it in the vmalloc space. * just put it in the vmalloc space.
*/ */
#if defined(CONFIG_MODULES) && defined(MODULES_VADDR) #if defined(CONFIG_MODULES) && defined(MODULES_VADDR)
unsigned long addr = (unsigned long)x; unsigned long addr = (unsigned long)kasan_reset_tag(x);
if (addr >= MODULES_VADDR && addr < MODULES_END) if (addr >= MODULES_VADDR && addr < MODULES_END)
return 1; return 1;
#endif #endif
...@@ -795,6 +795,8 @@ static struct vmap_area *find_vmap_area_exceed_addr(unsigned long addr) ...@@ -795,6 +795,8 @@ static struct vmap_area *find_vmap_area_exceed_addr(unsigned long addr)
struct vmap_area *va = NULL; struct vmap_area *va = NULL;
struct rb_node *n = vmap_area_root.rb_node; struct rb_node *n = vmap_area_root.rb_node;
addr = (unsigned long)kasan_reset_tag((void *)addr);
while (n) { while (n) {
struct vmap_area *tmp; struct vmap_area *tmp;
...@@ -816,6 +818,8 @@ static struct vmap_area *__find_vmap_area(unsigned long addr) ...@@ -816,6 +818,8 @@ static struct vmap_area *__find_vmap_area(unsigned long addr)
{ {
struct rb_node *n = vmap_area_root.rb_node; struct rb_node *n = vmap_area_root.rb_node;
addr = (unsigned long)kasan_reset_tag((void *)addr);
while (n) { while (n) {
struct vmap_area *va; struct vmap_area *va;
...@@ -2166,7 +2170,7 @@ EXPORT_SYMBOL_GPL(vm_unmap_aliases); ...@@ -2166,7 +2170,7 @@ EXPORT_SYMBOL_GPL(vm_unmap_aliases);
void vm_unmap_ram(const void *mem, unsigned int count) void vm_unmap_ram(const void *mem, unsigned int count)
{ {
unsigned long size = (unsigned long)count << PAGE_SHIFT; unsigned long size = (unsigned long)count << PAGE_SHIFT;
unsigned long addr = (unsigned long)mem; unsigned long addr = (unsigned long)kasan_reset_tag(mem);
struct vmap_area *va; struct vmap_area *va;
might_sleep(); might_sleep();
...@@ -3424,6 +3428,8 @@ long vread(char *buf, char *addr, unsigned long count) ...@@ -3424,6 +3428,8 @@ long vread(char *buf, char *addr, unsigned long count)
unsigned long buflen = count; unsigned long buflen = count;
unsigned long n; unsigned long n;
addr = kasan_reset_tag(addr);
/* Don't allow overflow */ /* Don't allow overflow */
if ((unsigned long) addr + count < count) if ((unsigned long) addr + count < count)
count = -(unsigned long) addr; count = -(unsigned long) addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment