mm/kmsan/hooks.c

Source file repositories/reference/linux-study-clean/mm/kmsan/hooks.c

File Facts

System
Linux kernel
Corpus path
mm/kmsan/hooks.c
Extension
.c
Size
12063 bytes
Lines
443
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

if (!shadow || !origin) {
			err = -ENOMEM;
			goto ret;
		}
		mapped = __vmap_pages_range_noflush(
			vmalloc_shadow(start + off),
			vmalloc_shadow(start + off + PAGE_SIZE), prot, &shadow,
			PAGE_SHIFT);
		if (mapped) {
			err = mapped;
			goto ret;
		}
		shadow = NULL;
		mapped = __vmap_pages_range_noflush(
			vmalloc_origin(start + off),
			vmalloc_origin(start + off + PAGE_SIZE), prot, &origin,
			PAGE_SHIFT);
		if (mapped) {
			__vunmap_range_noflush(
				vmalloc_shadow(start + off),
				vmalloc_shadow(start + off + PAGE_SIZE));
			err = mapped;
			goto ret;
		}
		origin = NULL;
	}
	/* Page mapping loop finished normally, nothing to clean up. */
	clean = 0;

ret:
	if (clean > 0) {
		/*
		 * Something went wrong. Clean up shadow/origin pages allocated
		 * on the last loop iteration, then delete mappings created
		 * during the previous iterations.
		 */
		if (shadow)
			__free_pages(shadow, 1);
		if (origin)
			__free_pages(origin, 1);
		__vunmap_range_noflush(
			vmalloc_shadow(start),
			vmalloc_shadow(start + clean * PAGE_SIZE));
		__vunmap_range_noflush(
			vmalloc_origin(start),
			vmalloc_origin(start + clean * PAGE_SIZE));
	}
	flush_cache_vmap(vmalloc_shadow(start), vmalloc_shadow(end));
	flush_cache_vmap(vmalloc_origin(start), vmalloc_origin(end));
	kmsan_leave_runtime();
	return err;
}

void kmsan_iounmap_page_range(unsigned long start, unsigned long end)
{
	unsigned long v_shadow, v_origin;
	struct page *shadow, *origin;
	int nr;

	if (!kmsan_enabled || kmsan_in_runtime())
		return;

	nr = (end - start) / PAGE_SIZE;
	kmsan_enter_runtime();
	v_shadow = (unsigned long)vmalloc_shadow(start);
	v_origin = (unsigned long)vmalloc_origin(start);
	for (int i = 0; i < nr;
	     i++, v_shadow += PAGE_SIZE, v_origin += PAGE_SIZE) {
		shadow = kmsan_vmalloc_to_page_or_null((void *)v_shadow);
		origin = kmsan_vmalloc_to_page_or_null((void *)v_origin);
		__vunmap_range_noflush(v_shadow, vmalloc_shadow(end));
		__vunmap_range_noflush(v_origin, vmalloc_origin(end));
		if (shadow)
			__free_pages(shadow, 1);
		if (origin)
			__free_pages(origin, 1);
	}
	flush_cache_vmap(vmalloc_shadow(start), vmalloc_shadow(end));
	flush_cache_vmap(vmalloc_origin(start), vmalloc_origin(end));
	kmsan_leave_runtime();
}

void kmsan_copy_to_user(void __user *to, const void *from, size_t to_copy,
			size_t left)
{
	unsigned long ua_flags;

	if (!kmsan_enabled || kmsan_in_runtime())
		return;
	/*

Annotation

Implementation Notes