mm/kasan/shadow.c

Source file repositories/reference/linux-study-clean/mm/kasan/shadow.c

File Facts

System
Linux kernel
Corpus path
mm/kasan/shadow.c
Extension
.c
Size
20035 bytes
Lines
707
Domain
Core OS
Bucket
Memory Management
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

core_initcall(kasan_memhotplug_init);
#endif

#ifdef CONFIG_KASAN_VMALLOC

void __init __weak kasan_populate_early_vm_area_shadow(void *start,
						       unsigned long size)
{
}

struct vmalloc_populate_data {
	unsigned long start;
	struct page **pages;
};

static int kasan_populate_vmalloc_pte(pte_t *ptep, unsigned long addr,
				      void *_data)
{
	struct vmalloc_populate_data *data = _data;
	struct page *page;
	pte_t pte;
	int index;

	lazy_mmu_mode_pause();

	index = PFN_DOWN(addr - data->start);
	page = data->pages[index];
	__memset(page_to_virt(page), KASAN_VMALLOC_INVALID, PAGE_SIZE);
	pte = pfn_pte(page_to_pfn(page), PAGE_KERNEL);

	spin_lock(&init_mm.page_table_lock);
	if (likely(pte_none(ptep_get(ptep)))) {
		set_pte_at(&init_mm, addr, ptep, pte);
		data->pages[index] = NULL;
	}
	spin_unlock(&init_mm.page_table_lock);

	lazy_mmu_mode_resume();

	return 0;
}

static void ___free_pages_bulk(struct page **pages, int nr_pages)
{
	int i;

	for (i = 0; i < nr_pages; i++) {
		if (pages[i]) {
			__free_pages(pages[i], 0);
			pages[i] = NULL;
		}
	}
}

static int ___alloc_pages_bulk(struct page **pages, int nr_pages, gfp_t gfp_mask)
{
	unsigned long nr_populated, nr_total = nr_pages;
	struct page **page_array = pages;

	while (nr_pages) {
		nr_populated = alloc_pages_bulk(gfp_mask, nr_pages, pages);
		if (!nr_populated) {
			___free_pages_bulk(page_array, nr_total - nr_pages);
			return -ENOMEM;
		}
		pages += nr_populated;
		nr_pages -= nr_populated;
	}

	return 0;
}

static int __kasan_populate_vmalloc_do(unsigned long start, unsigned long end, gfp_t gfp_mask)
{
	unsigned long nr_pages, nr_total = PFN_UP(end - start);
	struct vmalloc_populate_data data;
	unsigned int flags;
	int ret = 0;

	data.pages = (struct page **)__get_free_page(gfp_mask | __GFP_ZERO);
	if (!data.pages)
		return -ENOMEM;

	while (nr_total) {
		nr_pages = min(nr_total, PAGE_SIZE / sizeof(data.pages[0]));
		ret = ___alloc_pages_bulk(data.pages, nr_pages, gfp_mask);
		if (ret)
			break;

		data.start = start;

Annotation

Implementation Notes