From 9384a0909faf38f44986663065e5419861a3d773 Mon Sep 17 00:00:00 2001 From: Vincent Donnefort Date: Fri, 24 Jan 2025 09:38:16 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Refine pKVM module kmemleak scanned areas With b319cea80539 ("module: Refine kmemleak scanned areas"), the module loader does not use kmemleak_scan_area() anymore. This means we can leverage it while loading EL2 sections for a finer-grain selection of kmemleak scanned regions. In other words, bring back kmemleak scanning for EL1 RW ELF sections. Bug: 357781595 Bug: 244543039 Bug: 244373730 Change-Id: I14cd9ba8a6d0e94e5f2d1710280b5a1c4633df81 Signed-off-by: Vincent Donnefort --- arch/arm64/kvm/pkvm.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index 891bebdbe0da..3bc8fd3044ae 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -1051,6 +1051,37 @@ static void pkvm_unmap_module_struct(void *addr) free_page((unsigned long)addr); } +static void pkvm_module_kmemleak(struct module *this, + struct pkvm_mod_sec_mapping *sec_map, + int nr_sections) +{ + void *start, *end; + int i; + + if (!this) + return; + + /* + * The module loader already removes read-only sections from kmemleak + * scanned objects. However, few hyp sections are installed into + * MOD_DATA. Skip those sections before they are made inaccessible from + * the host. + */ + + start = this->mem[MOD_DATA].base; + end = start + this->mem[MOD_DATA].size; + + for (i = 0; i < nr_sections; i++, sec_map++) { + if (sec_map->sec->start < start || sec_map->sec->start >= end) + continue; + + kmemleak_scan_area(start, sec_map->sec->start - start, GFP_KERNEL); + start = sec_map->sec->end; + } + + kmemleak_scan_area(start, end - start, GFP_KERNEL); +} + int __pkvm_load_el2_module(struct module *this, unsigned long *token) { struct pkvm_el2_module *mod = &this->arch.hyp; @@ -1124,16 +1155,7 @@ int __pkvm_load_el2_module(struct module *this, unsigned long *token) if (ret) return ret; - /* - * Sadly we have also to disable kmemleak for EL1 sections: we can't - * reset created scan area and therefore we can't create a finer grain - * scan excluding only EL2 sections. - */ - if (this) { - kmemleak_no_scan(this->mem[MOD_TEXT].base); - kmemleak_no_scan(this->mem[MOD_DATA].base); - kmemleak_no_scan(this->mem[MOD_RODATA].base); - } + pkvm_module_kmemleak(this, secs_map, ARRAY_SIZE(secs_map)); ret = hyp_trace_init_mod_events(mod->hyp_events, mod->event_ids.start,