162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file contains KASAN runtime code that manages shadow memory for
462306a36Sopenharmony_ci * generic and software tag-based KASAN modes.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (c) 2014 Samsung Electronics Co., Ltd.
762306a36Sopenharmony_ci * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Some code borrowed from https://github.com/xairy/kasan-prototype by
1062306a36Sopenharmony_ci *        Andrey Konovalov <andreyknvl@gmail.com>
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/kasan.h>
1562306a36Sopenharmony_ci#include <linux/kernel.h>
1662306a36Sopenharmony_ci#include <linux/kfence.h>
1762306a36Sopenharmony_ci#include <linux/kmemleak.h>
1862306a36Sopenharmony_ci#include <linux/memory.h>
1962306a36Sopenharmony_ci#include <linux/mm.h>
2062306a36Sopenharmony_ci#include <linux/string.h>
2162306a36Sopenharmony_ci#include <linux/types.h>
2262306a36Sopenharmony_ci#include <linux/vmalloc.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include <asm/cacheflush.h>
2562306a36Sopenharmony_ci#include <asm/tlbflush.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "kasan.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cibool __kasan_check_read(const volatile void *p, unsigned int size)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	return kasan_check_range((void *)p, size, false, _RET_IP_);
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ciEXPORT_SYMBOL(__kasan_check_read);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cibool __kasan_check_write(const volatile void *p, unsigned int size)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	return kasan_check_range((void *)p, size, true, _RET_IP_);
3862306a36Sopenharmony_ci}
3962306a36Sopenharmony_ciEXPORT_SYMBOL(__kasan_check_write);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#if !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX) && !defined(CONFIG_GENERIC_ENTRY)
4262306a36Sopenharmony_ci/*
4362306a36Sopenharmony_ci * CONFIG_GENERIC_ENTRY relies on compiler emitted mem*() calls to not be
4462306a36Sopenharmony_ci * instrumented. KASAN enabled toolchains should emit __asan_mem*() functions
4562306a36Sopenharmony_ci * for the sites they want to instrument.
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * If we have a compiler that can instrument meminstrinsics, never override
4862306a36Sopenharmony_ci * these, so that non-instrumented files can safely consider them as builtins.
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ci#undef memset
5162306a36Sopenharmony_civoid *memset(void *addr, int c, size_t len)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	if (!kasan_check_range(addr, len, true, _RET_IP_))
5462306a36Sopenharmony_ci		return NULL;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	return __memset(addr, c, len);
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#ifdef __HAVE_ARCH_MEMMOVE
6062306a36Sopenharmony_ci#undef memmove
6162306a36Sopenharmony_civoid *memmove(void *dest, const void *src, size_t len)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	if (!kasan_check_range(src, len, false, _RET_IP_) ||
6462306a36Sopenharmony_ci	    !kasan_check_range(dest, len, true, _RET_IP_))
6562306a36Sopenharmony_ci		return NULL;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	return __memmove(dest, src, len);
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci#endif
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci#undef memcpy
7262306a36Sopenharmony_civoid *memcpy(void *dest, const void *src, size_t len)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	if (!kasan_check_range(src, len, false, _RET_IP_) ||
7562306a36Sopenharmony_ci	    !kasan_check_range(dest, len, true, _RET_IP_))
7662306a36Sopenharmony_ci		return NULL;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	return __memcpy(dest, src, len);
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci#endif
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_civoid *__asan_memset(void *addr, int c, ssize_t len)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	if (!kasan_check_range(addr, len, true, _RET_IP_))
8562306a36Sopenharmony_ci		return NULL;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	return __memset(addr, c, len);
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ciEXPORT_SYMBOL(__asan_memset);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci#ifdef __HAVE_ARCH_MEMMOVE
9262306a36Sopenharmony_civoid *__asan_memmove(void *dest, const void *src, ssize_t len)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	if (!kasan_check_range(src, len, false, _RET_IP_) ||
9562306a36Sopenharmony_ci	    !kasan_check_range(dest, len, true, _RET_IP_))
9662306a36Sopenharmony_ci		return NULL;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	return __memmove(dest, src, len);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ciEXPORT_SYMBOL(__asan_memmove);
10162306a36Sopenharmony_ci#endif
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_civoid *__asan_memcpy(void *dest, const void *src, ssize_t len)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	if (!kasan_check_range(src, len, false, _RET_IP_) ||
10662306a36Sopenharmony_ci	    !kasan_check_range(dest, len, true, _RET_IP_))
10762306a36Sopenharmony_ci		return NULL;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	return __memcpy(dest, src, len);
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ciEXPORT_SYMBOL(__asan_memcpy);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci#ifdef CONFIG_KASAN_SW_TAGS
11462306a36Sopenharmony_civoid *__hwasan_memset(void *addr, int c, ssize_t len) __alias(__asan_memset);
11562306a36Sopenharmony_ciEXPORT_SYMBOL(__hwasan_memset);
11662306a36Sopenharmony_ci#ifdef __HAVE_ARCH_MEMMOVE
11762306a36Sopenharmony_civoid *__hwasan_memmove(void *dest, const void *src, ssize_t len) __alias(__asan_memmove);
11862306a36Sopenharmony_ciEXPORT_SYMBOL(__hwasan_memmove);
11962306a36Sopenharmony_ci#endif
12062306a36Sopenharmony_civoid *__hwasan_memcpy(void *dest, const void *src, ssize_t len) __alias(__asan_memcpy);
12162306a36Sopenharmony_ciEXPORT_SYMBOL(__hwasan_memcpy);
12262306a36Sopenharmony_ci#endif
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_civoid kasan_poison(const void *addr, size_t size, u8 value, bool init)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	void *shadow_start, *shadow_end;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	if (!kasan_arch_is_ready())
12962306a36Sopenharmony_ci		return;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	/*
13262306a36Sopenharmony_ci	 * Perform shadow offset calculation based on untagged address, as
13362306a36Sopenharmony_ci	 * some of the callers (e.g. kasan_poison_object_data) pass tagged
13462306a36Sopenharmony_ci	 * addresses to this function.
13562306a36Sopenharmony_ci	 */
13662306a36Sopenharmony_ci	addr = kasan_reset_tag(addr);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	/* Skip KFENCE memory if called explicitly outside of sl*b. */
13962306a36Sopenharmony_ci	if (is_kfence_address(addr))
14062306a36Sopenharmony_ci		return;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	if (WARN_ON((unsigned long)addr & KASAN_GRANULE_MASK))
14362306a36Sopenharmony_ci		return;
14462306a36Sopenharmony_ci	if (WARN_ON(size & KASAN_GRANULE_MASK))
14562306a36Sopenharmony_ci		return;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	shadow_start = kasan_mem_to_shadow(addr);
14862306a36Sopenharmony_ci	shadow_end = kasan_mem_to_shadow(addr + size);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	__memset(shadow_start, value, shadow_end - shadow_start);
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ciEXPORT_SYMBOL(kasan_poison);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci#ifdef CONFIG_KASAN_GENERIC
15562306a36Sopenharmony_civoid kasan_poison_last_granule(const void *addr, size_t size)
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci	if (!kasan_arch_is_ready())
15862306a36Sopenharmony_ci		return;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	if (size & KASAN_GRANULE_MASK) {
16162306a36Sopenharmony_ci		u8 *shadow = (u8 *)kasan_mem_to_shadow(addr + size);
16262306a36Sopenharmony_ci		*shadow = size & KASAN_GRANULE_MASK;
16362306a36Sopenharmony_ci	}
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci#endif
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_civoid kasan_unpoison(const void *addr, size_t size, bool init)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	u8 tag = get_tag(addr);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	/*
17262306a36Sopenharmony_ci	 * Perform shadow offset calculation based on untagged address, as
17362306a36Sopenharmony_ci	 * some of the callers (e.g. kasan_unpoison_object_data) pass tagged
17462306a36Sopenharmony_ci	 * addresses to this function.
17562306a36Sopenharmony_ci	 */
17662306a36Sopenharmony_ci	addr = kasan_reset_tag(addr);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	/*
17962306a36Sopenharmony_ci	 * Skip KFENCE memory if called explicitly outside of sl*b. Also note
18062306a36Sopenharmony_ci	 * that calls to ksize(), where size is not a multiple of machine-word
18162306a36Sopenharmony_ci	 * size, would otherwise poison the invalid portion of the word.
18262306a36Sopenharmony_ci	 */
18362306a36Sopenharmony_ci	if (is_kfence_address(addr))
18462306a36Sopenharmony_ci		return;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	if (WARN_ON((unsigned long)addr & KASAN_GRANULE_MASK))
18762306a36Sopenharmony_ci		return;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	/* Unpoison all granules that cover the object. */
19062306a36Sopenharmony_ci	kasan_poison(addr, round_up(size, KASAN_GRANULE_SIZE), tag, false);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	/* Partially poison the last granule for the generic mode. */
19362306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_KASAN_GENERIC))
19462306a36Sopenharmony_ci		kasan_poison_last_granule(addr, size);
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci#ifdef CONFIG_MEMORY_HOTPLUG
19862306a36Sopenharmony_cistatic bool shadow_mapped(unsigned long addr)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	pgd_t *pgd = pgd_offset_k(addr);
20162306a36Sopenharmony_ci	p4d_t *p4d;
20262306a36Sopenharmony_ci	pud_t *pud;
20362306a36Sopenharmony_ci	pmd_t *pmd;
20462306a36Sopenharmony_ci	pte_t *pte;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	if (pgd_none(*pgd))
20762306a36Sopenharmony_ci		return false;
20862306a36Sopenharmony_ci	p4d = p4d_offset(pgd, addr);
20962306a36Sopenharmony_ci	if (p4d_none(*p4d))
21062306a36Sopenharmony_ci		return false;
21162306a36Sopenharmony_ci	pud = pud_offset(p4d, addr);
21262306a36Sopenharmony_ci	if (pud_none(*pud))
21362306a36Sopenharmony_ci		return false;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	/*
21662306a36Sopenharmony_ci	 * We can't use pud_large() or pud_huge(), the first one is
21762306a36Sopenharmony_ci	 * arch-specific, the last one depends on HUGETLB_PAGE.  So let's abuse
21862306a36Sopenharmony_ci	 * pud_bad(), if pud is bad then it's bad because it's huge.
21962306a36Sopenharmony_ci	 */
22062306a36Sopenharmony_ci	if (pud_bad(*pud))
22162306a36Sopenharmony_ci		return true;
22262306a36Sopenharmony_ci	pmd = pmd_offset(pud, addr);
22362306a36Sopenharmony_ci	if (pmd_none(*pmd))
22462306a36Sopenharmony_ci		return false;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	if (pmd_bad(*pmd))
22762306a36Sopenharmony_ci		return true;
22862306a36Sopenharmony_ci	pte = pte_offset_kernel(pmd, addr);
22962306a36Sopenharmony_ci	return !pte_none(ptep_get(pte));
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic int __meminit kasan_mem_notifier(struct notifier_block *nb,
23362306a36Sopenharmony_ci			unsigned long action, void *data)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	struct memory_notify *mem_data = data;
23662306a36Sopenharmony_ci	unsigned long nr_shadow_pages, start_kaddr, shadow_start;
23762306a36Sopenharmony_ci	unsigned long shadow_end, shadow_size;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	nr_shadow_pages = mem_data->nr_pages >> KASAN_SHADOW_SCALE_SHIFT;
24062306a36Sopenharmony_ci	start_kaddr = (unsigned long)pfn_to_kaddr(mem_data->start_pfn);
24162306a36Sopenharmony_ci	shadow_start = (unsigned long)kasan_mem_to_shadow((void *)start_kaddr);
24262306a36Sopenharmony_ci	shadow_size = nr_shadow_pages << PAGE_SHIFT;
24362306a36Sopenharmony_ci	shadow_end = shadow_start + shadow_size;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	if (WARN_ON(mem_data->nr_pages % KASAN_GRANULE_SIZE) ||
24662306a36Sopenharmony_ci		WARN_ON(start_kaddr % KASAN_MEMORY_PER_SHADOW_PAGE))
24762306a36Sopenharmony_ci		return NOTIFY_BAD;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	switch (action) {
25062306a36Sopenharmony_ci	case MEM_GOING_ONLINE: {
25162306a36Sopenharmony_ci		void *ret;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci		/*
25462306a36Sopenharmony_ci		 * If shadow is mapped already than it must have been mapped
25562306a36Sopenharmony_ci		 * during the boot. This could happen if we onlining previously
25662306a36Sopenharmony_ci		 * offlined memory.
25762306a36Sopenharmony_ci		 */
25862306a36Sopenharmony_ci		if (shadow_mapped(shadow_start))
25962306a36Sopenharmony_ci			return NOTIFY_OK;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci		ret = __vmalloc_node_range(shadow_size, PAGE_SIZE, shadow_start,
26262306a36Sopenharmony_ci					shadow_end, GFP_KERNEL,
26362306a36Sopenharmony_ci					PAGE_KERNEL, VM_NO_GUARD,
26462306a36Sopenharmony_ci					pfn_to_nid(mem_data->start_pfn),
26562306a36Sopenharmony_ci					__builtin_return_address(0));
26662306a36Sopenharmony_ci		if (!ret)
26762306a36Sopenharmony_ci			return NOTIFY_BAD;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci		kmemleak_ignore(ret);
27062306a36Sopenharmony_ci		return NOTIFY_OK;
27162306a36Sopenharmony_ci	}
27262306a36Sopenharmony_ci	case MEM_CANCEL_ONLINE:
27362306a36Sopenharmony_ci	case MEM_OFFLINE: {
27462306a36Sopenharmony_ci		struct vm_struct *vm;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci		/*
27762306a36Sopenharmony_ci		 * shadow_start was either mapped during boot by kasan_init()
27862306a36Sopenharmony_ci		 * or during memory online by __vmalloc_node_range().
27962306a36Sopenharmony_ci		 * In the latter case we can use vfree() to free shadow.
28062306a36Sopenharmony_ci		 * Non-NULL result of the find_vm_area() will tell us if
28162306a36Sopenharmony_ci		 * that was the second case.
28262306a36Sopenharmony_ci		 *
28362306a36Sopenharmony_ci		 * Currently it's not possible to free shadow mapped
28462306a36Sopenharmony_ci		 * during boot by kasan_init(). It's because the code
28562306a36Sopenharmony_ci		 * to do that hasn't been written yet. So we'll just
28662306a36Sopenharmony_ci		 * leak the memory.
28762306a36Sopenharmony_ci		 */
28862306a36Sopenharmony_ci		vm = find_vm_area((void *)shadow_start);
28962306a36Sopenharmony_ci		if (vm)
29062306a36Sopenharmony_ci			vfree((void *)shadow_start);
29162306a36Sopenharmony_ci	}
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	return NOTIFY_OK;
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistatic int __init kasan_memhotplug_init(void)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	hotplug_memory_notifier(kasan_mem_notifier, DEFAULT_CALLBACK_PRI);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	return 0;
30262306a36Sopenharmony_ci}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_cicore_initcall(kasan_memhotplug_init);
30562306a36Sopenharmony_ci#endif
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci#ifdef CONFIG_KASAN_VMALLOC
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_civoid __init __weak kasan_populate_early_vm_area_shadow(void *start,
31062306a36Sopenharmony_ci						       unsigned long size)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_cistatic int kasan_populate_vmalloc_pte(pte_t *ptep, unsigned long addr,
31562306a36Sopenharmony_ci				      void *unused)
31662306a36Sopenharmony_ci{
31762306a36Sopenharmony_ci	unsigned long page;
31862306a36Sopenharmony_ci	pte_t pte;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	if (likely(!pte_none(ptep_get(ptep))))
32162306a36Sopenharmony_ci		return 0;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	page = __get_free_page(GFP_KERNEL);
32462306a36Sopenharmony_ci	if (!page)
32562306a36Sopenharmony_ci		return -ENOMEM;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	memset((void *)page, KASAN_VMALLOC_INVALID, PAGE_SIZE);
32862306a36Sopenharmony_ci	pte = pfn_pte(PFN_DOWN(__pa(page)), PAGE_KERNEL);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	spin_lock(&init_mm.page_table_lock);
33162306a36Sopenharmony_ci	if (likely(pte_none(ptep_get(ptep)))) {
33262306a36Sopenharmony_ci		set_pte_at(&init_mm, addr, ptep, pte);
33362306a36Sopenharmony_ci		page = 0;
33462306a36Sopenharmony_ci	}
33562306a36Sopenharmony_ci	spin_unlock(&init_mm.page_table_lock);
33662306a36Sopenharmony_ci	if (page)
33762306a36Sopenharmony_ci		free_page(page);
33862306a36Sopenharmony_ci	return 0;
33962306a36Sopenharmony_ci}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ciint kasan_populate_vmalloc(unsigned long addr, unsigned long size)
34262306a36Sopenharmony_ci{
34362306a36Sopenharmony_ci	unsigned long shadow_start, shadow_end;
34462306a36Sopenharmony_ci	int ret;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	if (!kasan_arch_is_ready())
34762306a36Sopenharmony_ci		return 0;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	if (!is_vmalloc_or_module_addr((void *)addr))
35062306a36Sopenharmony_ci		return 0;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	shadow_start = (unsigned long)kasan_mem_to_shadow((void *)addr);
35362306a36Sopenharmony_ci	shadow_end = (unsigned long)kasan_mem_to_shadow((void *)addr + size);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	/*
35662306a36Sopenharmony_ci	 * User Mode Linux maps enough shadow memory for all of virtual memory
35762306a36Sopenharmony_ci	 * at boot, so doesn't need to allocate more on vmalloc, just clear it.
35862306a36Sopenharmony_ci	 *
35962306a36Sopenharmony_ci	 * The remaining CONFIG_UML checks in this file exist for the same
36062306a36Sopenharmony_ci	 * reason.
36162306a36Sopenharmony_ci	 */
36262306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_UML)) {
36362306a36Sopenharmony_ci		__memset((void *)shadow_start, KASAN_VMALLOC_INVALID, shadow_end - shadow_start);
36462306a36Sopenharmony_ci		return 0;
36562306a36Sopenharmony_ci	}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	shadow_start = PAGE_ALIGN_DOWN(shadow_start);
36862306a36Sopenharmony_ci	shadow_end = PAGE_ALIGN(shadow_end);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	ret = apply_to_page_range(&init_mm, shadow_start,
37162306a36Sopenharmony_ci				  shadow_end - shadow_start,
37262306a36Sopenharmony_ci				  kasan_populate_vmalloc_pte, NULL);
37362306a36Sopenharmony_ci	if (ret)
37462306a36Sopenharmony_ci		return ret;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	flush_cache_vmap(shadow_start, shadow_end);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	/*
37962306a36Sopenharmony_ci	 * We need to be careful about inter-cpu effects here. Consider:
38062306a36Sopenharmony_ci	 *
38162306a36Sopenharmony_ci	 *   CPU#0				  CPU#1
38262306a36Sopenharmony_ci	 * WRITE_ONCE(p, vmalloc(100));		while (x = READ_ONCE(p)) ;
38362306a36Sopenharmony_ci	 *					p[99] = 1;
38462306a36Sopenharmony_ci	 *
38562306a36Sopenharmony_ci	 * With compiler instrumentation, that ends up looking like this:
38662306a36Sopenharmony_ci	 *
38762306a36Sopenharmony_ci	 *   CPU#0				  CPU#1
38862306a36Sopenharmony_ci	 * // vmalloc() allocates memory
38962306a36Sopenharmony_ci	 * // let a = area->addr
39062306a36Sopenharmony_ci	 * // we reach kasan_populate_vmalloc
39162306a36Sopenharmony_ci	 * // and call kasan_unpoison:
39262306a36Sopenharmony_ci	 * STORE shadow(a), unpoison_val
39362306a36Sopenharmony_ci	 * ...
39462306a36Sopenharmony_ci	 * STORE shadow(a+99), unpoison_val	x = LOAD p
39562306a36Sopenharmony_ci	 * // rest of vmalloc process		<data dependency>
39662306a36Sopenharmony_ci	 * STORE p, a				LOAD shadow(x+99)
39762306a36Sopenharmony_ci	 *
39862306a36Sopenharmony_ci	 * If there is no barrier between the end of unpoisoning the shadow
39962306a36Sopenharmony_ci	 * and the store of the result to p, the stores could be committed
40062306a36Sopenharmony_ci	 * in a different order by CPU#0, and CPU#1 could erroneously observe
40162306a36Sopenharmony_ci	 * poison in the shadow.
40262306a36Sopenharmony_ci	 *
40362306a36Sopenharmony_ci	 * We need some sort of barrier between the stores.
40462306a36Sopenharmony_ci	 *
40562306a36Sopenharmony_ci	 * In the vmalloc() case, this is provided by a smp_wmb() in
40662306a36Sopenharmony_ci	 * clear_vm_uninitialized_flag(). In the per-cpu allocator and in
40762306a36Sopenharmony_ci	 * get_vm_area() and friends, the caller gets shadow allocated but
40862306a36Sopenharmony_ci	 * doesn't have any pages mapped into the virtual address space that
40962306a36Sopenharmony_ci	 * has been reserved. Mapping those pages in will involve taking and
41062306a36Sopenharmony_ci	 * releasing a page-table lock, which will provide the barrier.
41162306a36Sopenharmony_ci	 */
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	return 0;
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic int kasan_depopulate_vmalloc_pte(pte_t *ptep, unsigned long addr,
41762306a36Sopenharmony_ci					void *unused)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	unsigned long page;
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	page = (unsigned long)__va(pte_pfn(ptep_get(ptep)) << PAGE_SHIFT);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	spin_lock(&init_mm.page_table_lock);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	if (likely(!pte_none(ptep_get(ptep)))) {
42662306a36Sopenharmony_ci		pte_clear(&init_mm, addr, ptep);
42762306a36Sopenharmony_ci		free_page(page);
42862306a36Sopenharmony_ci	}
42962306a36Sopenharmony_ci	spin_unlock(&init_mm.page_table_lock);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	return 0;
43262306a36Sopenharmony_ci}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci/*
43562306a36Sopenharmony_ci * Release the backing for the vmalloc region [start, end), which
43662306a36Sopenharmony_ci * lies within the free region [free_region_start, free_region_end).
43762306a36Sopenharmony_ci *
43862306a36Sopenharmony_ci * This can be run lazily, long after the region was freed. It runs
43962306a36Sopenharmony_ci * under vmap_area_lock, so it's not safe to interact with the vmalloc/vmap
44062306a36Sopenharmony_ci * infrastructure.
44162306a36Sopenharmony_ci *
44262306a36Sopenharmony_ci * How does this work?
44362306a36Sopenharmony_ci * -------------------
44462306a36Sopenharmony_ci *
44562306a36Sopenharmony_ci * We have a region that is page aligned, labeled as A.
44662306a36Sopenharmony_ci * That might not map onto the shadow in a way that is page-aligned:
44762306a36Sopenharmony_ci *
44862306a36Sopenharmony_ci *                    start                     end
44962306a36Sopenharmony_ci *                    v                         v
45062306a36Sopenharmony_ci * |????????|????????|AAAAAAAA|AA....AA|AAAAAAAA|????????| < vmalloc
45162306a36Sopenharmony_ci *  -------- -------- --------          -------- --------
45262306a36Sopenharmony_ci *      |        |       |                 |        |
45362306a36Sopenharmony_ci *      |        |       |         /-------/        |
45462306a36Sopenharmony_ci *      \-------\|/------/         |/---------------/
45562306a36Sopenharmony_ci *              |||                ||
45662306a36Sopenharmony_ci *             |??AAAAAA|AAAAAAAA|AA??????|                < shadow
45762306a36Sopenharmony_ci *                 (1)      (2)      (3)
45862306a36Sopenharmony_ci *
45962306a36Sopenharmony_ci * First we align the start upwards and the end downwards, so that the
46062306a36Sopenharmony_ci * shadow of the region aligns with shadow page boundaries. In the
46162306a36Sopenharmony_ci * example, this gives us the shadow page (2). This is the shadow entirely
46262306a36Sopenharmony_ci * covered by this allocation.
46362306a36Sopenharmony_ci *
46462306a36Sopenharmony_ci * Then we have the tricky bits. We want to know if we can free the
46562306a36Sopenharmony_ci * partially covered shadow pages - (1) and (3) in the example. For this,
46662306a36Sopenharmony_ci * we are given the start and end of the free region that contains this
46762306a36Sopenharmony_ci * allocation. Extending our previous example, we could have:
46862306a36Sopenharmony_ci *
46962306a36Sopenharmony_ci *  free_region_start                                    free_region_end
47062306a36Sopenharmony_ci *  |                 start                     end      |
47162306a36Sopenharmony_ci *  v                 v                         v        v
47262306a36Sopenharmony_ci * |FFFFFFFF|FFFFFFFF|AAAAAAAA|AA....AA|AAAAAAAA|FFFFFFFF| < vmalloc
47362306a36Sopenharmony_ci *  -------- -------- --------          -------- --------
47462306a36Sopenharmony_ci *      |        |       |                 |        |
47562306a36Sopenharmony_ci *      |        |       |         /-------/        |
47662306a36Sopenharmony_ci *      \-------\|/------/         |/---------------/
47762306a36Sopenharmony_ci *              |||                ||
47862306a36Sopenharmony_ci *             |FFAAAAAA|AAAAAAAA|AAF?????|                < shadow
47962306a36Sopenharmony_ci *                 (1)      (2)      (3)
48062306a36Sopenharmony_ci *
48162306a36Sopenharmony_ci * Once again, we align the start of the free region up, and the end of
48262306a36Sopenharmony_ci * the free region down so that the shadow is page aligned. So we can free
48362306a36Sopenharmony_ci * page (1) - we know no allocation currently uses anything in that page,
48462306a36Sopenharmony_ci * because all of it is in the vmalloc free region. But we cannot free
48562306a36Sopenharmony_ci * page (3), because we can't be sure that the rest of it is unused.
48662306a36Sopenharmony_ci *
48762306a36Sopenharmony_ci * We only consider pages that contain part of the original region for
48862306a36Sopenharmony_ci * freeing: we don't try to free other pages from the free region or we'd
48962306a36Sopenharmony_ci * end up trying to free huge chunks of virtual address space.
49062306a36Sopenharmony_ci *
49162306a36Sopenharmony_ci * Concurrency
49262306a36Sopenharmony_ci * -----------
49362306a36Sopenharmony_ci *
49462306a36Sopenharmony_ci * How do we know that we're not freeing a page that is simultaneously
49562306a36Sopenharmony_ci * being used for a fresh allocation in kasan_populate_vmalloc(_pte)?
49662306a36Sopenharmony_ci *
49762306a36Sopenharmony_ci * We _can_ have kasan_release_vmalloc and kasan_populate_vmalloc running
49862306a36Sopenharmony_ci * at the same time. While we run under free_vmap_area_lock, the population
49962306a36Sopenharmony_ci * code does not.
50062306a36Sopenharmony_ci *
50162306a36Sopenharmony_ci * free_vmap_area_lock instead operates to ensure that the larger range
50262306a36Sopenharmony_ci * [free_region_start, free_region_end) is safe: because __alloc_vmap_area and
50362306a36Sopenharmony_ci * the per-cpu region-finding algorithm both run under free_vmap_area_lock,
50462306a36Sopenharmony_ci * no space identified as free will become used while we are running. This
50562306a36Sopenharmony_ci * means that so long as we are careful with alignment and only free shadow
50662306a36Sopenharmony_ci * pages entirely covered by the free region, we will not run in to any
50762306a36Sopenharmony_ci * trouble - any simultaneous allocations will be for disjoint regions.
50862306a36Sopenharmony_ci */
50962306a36Sopenharmony_civoid kasan_release_vmalloc(unsigned long start, unsigned long end,
51062306a36Sopenharmony_ci			   unsigned long free_region_start,
51162306a36Sopenharmony_ci			   unsigned long free_region_end)
51262306a36Sopenharmony_ci{
51362306a36Sopenharmony_ci	void *shadow_start, *shadow_end;
51462306a36Sopenharmony_ci	unsigned long region_start, region_end;
51562306a36Sopenharmony_ci	unsigned long size;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	if (!kasan_arch_is_ready())
51862306a36Sopenharmony_ci		return;
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	region_start = ALIGN(start, KASAN_MEMORY_PER_SHADOW_PAGE);
52162306a36Sopenharmony_ci	region_end = ALIGN_DOWN(end, KASAN_MEMORY_PER_SHADOW_PAGE);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	free_region_start = ALIGN(free_region_start, KASAN_MEMORY_PER_SHADOW_PAGE);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	if (start != region_start &&
52662306a36Sopenharmony_ci	    free_region_start < region_start)
52762306a36Sopenharmony_ci		region_start -= KASAN_MEMORY_PER_SHADOW_PAGE;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	free_region_end = ALIGN_DOWN(free_region_end, KASAN_MEMORY_PER_SHADOW_PAGE);
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	if (end != region_end &&
53262306a36Sopenharmony_ci	    free_region_end > region_end)
53362306a36Sopenharmony_ci		region_end += KASAN_MEMORY_PER_SHADOW_PAGE;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	shadow_start = kasan_mem_to_shadow((void *)region_start);
53662306a36Sopenharmony_ci	shadow_end = kasan_mem_to_shadow((void *)region_end);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	if (shadow_end > shadow_start) {
53962306a36Sopenharmony_ci		size = shadow_end - shadow_start;
54062306a36Sopenharmony_ci		if (IS_ENABLED(CONFIG_UML)) {
54162306a36Sopenharmony_ci			__memset(shadow_start, KASAN_SHADOW_INIT, shadow_end - shadow_start);
54262306a36Sopenharmony_ci			return;
54362306a36Sopenharmony_ci		}
54462306a36Sopenharmony_ci		apply_to_existing_page_range(&init_mm,
54562306a36Sopenharmony_ci					     (unsigned long)shadow_start,
54662306a36Sopenharmony_ci					     size, kasan_depopulate_vmalloc_pte,
54762306a36Sopenharmony_ci					     NULL);
54862306a36Sopenharmony_ci		flush_tlb_kernel_range((unsigned long)shadow_start,
54962306a36Sopenharmony_ci				       (unsigned long)shadow_end);
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_civoid *__kasan_unpoison_vmalloc(const void *start, unsigned long size,
55462306a36Sopenharmony_ci			       kasan_vmalloc_flags_t flags)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	/*
55762306a36Sopenharmony_ci	 * Software KASAN modes unpoison both VM_ALLOC and non-VM_ALLOC
55862306a36Sopenharmony_ci	 * mappings, so the KASAN_VMALLOC_VM_ALLOC flag is ignored.
55962306a36Sopenharmony_ci	 * Software KASAN modes can't optimize zeroing memory by combining it
56062306a36Sopenharmony_ci	 * with setting memory tags, so the KASAN_VMALLOC_INIT flag is ignored.
56162306a36Sopenharmony_ci	 */
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	if (!kasan_arch_is_ready())
56462306a36Sopenharmony_ci		return (void *)start;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	if (!is_vmalloc_or_module_addr(start))
56762306a36Sopenharmony_ci		return (void *)start;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	/*
57062306a36Sopenharmony_ci	 * Don't tag executable memory with the tag-based mode.
57162306a36Sopenharmony_ci	 * The kernel doesn't tolerate having the PC register tagged.
57262306a36Sopenharmony_ci	 */
57362306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) &&
57462306a36Sopenharmony_ci	    !(flags & KASAN_VMALLOC_PROT_NORMAL))
57562306a36Sopenharmony_ci		return (void *)start;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	start = set_tag(start, kasan_random_tag());
57862306a36Sopenharmony_ci	kasan_unpoison(start, size, false);
57962306a36Sopenharmony_ci	return (void *)start;
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci/*
58362306a36Sopenharmony_ci * Poison the shadow for a vmalloc region. Called as part of the
58462306a36Sopenharmony_ci * freeing process at the time the region is freed.
58562306a36Sopenharmony_ci */
58662306a36Sopenharmony_civoid __kasan_poison_vmalloc(const void *start, unsigned long size)
58762306a36Sopenharmony_ci{
58862306a36Sopenharmony_ci	if (!kasan_arch_is_ready())
58962306a36Sopenharmony_ci		return;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	if (!is_vmalloc_or_module_addr(start))
59262306a36Sopenharmony_ci		return;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	size = round_up(size, KASAN_GRANULE_SIZE);
59562306a36Sopenharmony_ci	kasan_poison(start, size, KASAN_VMALLOC_INVALID, false);
59662306a36Sopenharmony_ci}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci#else /* CONFIG_KASAN_VMALLOC */
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ciint kasan_alloc_module_shadow(void *addr, size_t size, gfp_t gfp_mask)
60162306a36Sopenharmony_ci{
60262306a36Sopenharmony_ci	void *ret;
60362306a36Sopenharmony_ci	size_t scaled_size;
60462306a36Sopenharmony_ci	size_t shadow_size;
60562306a36Sopenharmony_ci	unsigned long shadow_start;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	shadow_start = (unsigned long)kasan_mem_to_shadow(addr);
60862306a36Sopenharmony_ci	scaled_size = (size + KASAN_GRANULE_SIZE - 1) >>
60962306a36Sopenharmony_ci				KASAN_SHADOW_SCALE_SHIFT;
61062306a36Sopenharmony_ci	shadow_size = round_up(scaled_size, PAGE_SIZE);
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	if (WARN_ON(!PAGE_ALIGNED(shadow_start)))
61362306a36Sopenharmony_ci		return -EINVAL;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_UML)) {
61662306a36Sopenharmony_ci		__memset((void *)shadow_start, KASAN_SHADOW_INIT, shadow_size);
61762306a36Sopenharmony_ci		return 0;
61862306a36Sopenharmony_ci	}
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	ret = __vmalloc_node_range(shadow_size, 1, shadow_start,
62162306a36Sopenharmony_ci			shadow_start + shadow_size,
62262306a36Sopenharmony_ci			GFP_KERNEL,
62362306a36Sopenharmony_ci			PAGE_KERNEL, VM_NO_GUARD, NUMA_NO_NODE,
62462306a36Sopenharmony_ci			__builtin_return_address(0));
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	if (ret) {
62762306a36Sopenharmony_ci		struct vm_struct *vm = find_vm_area(addr);
62862306a36Sopenharmony_ci		__memset(ret, KASAN_SHADOW_INIT, shadow_size);
62962306a36Sopenharmony_ci		vm->flags |= VM_KASAN;
63062306a36Sopenharmony_ci		kmemleak_ignore(ret);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci		if (vm->flags & VM_DEFER_KMEMLEAK)
63362306a36Sopenharmony_ci			kmemleak_vmalloc(vm, size, gfp_mask);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci		return 0;
63662306a36Sopenharmony_ci	}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	return -ENOMEM;
63962306a36Sopenharmony_ci}
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_civoid kasan_free_module_shadow(const struct vm_struct *vm)
64262306a36Sopenharmony_ci{
64362306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_UML))
64462306a36Sopenharmony_ci		return;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	if (vm->flags & VM_KASAN)
64762306a36Sopenharmony_ci		vfree(kasan_mem_to_shadow(vm->addr));
64862306a36Sopenharmony_ci}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci#endif
651