ANDROID: KVM: arm64: Refine pKVM module kmemleak scanned areas

With b319cea805 ("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 <vdonnefort@google.com>
This commit is contained in:
Vincent Donnefort
2025-01-24 09:38:16 +00:00
parent b556e0c960
commit 9384a0909f
+32 -10
View File
@@ -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,