linux: Unmap the VDSO page when unloading

linux_shared_page_init() creates an object and grabs and maps a single
page to back the VDSO.  When destroying the VDSO object, we failed to
destroy the mapping and free KVA.  Fix this.

Reviewed by:	kib
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D28696
This commit is contained in:
Mark Johnston 2021-02-16 09:30:21 -05:00
parent 2d936e6c99
commit 0fc8a79672
5 changed files with 12 additions and 5 deletions

View File

@ -818,7 +818,8 @@ static void
linux_vdso_deinstall(void *param)
{
__elfN(linux_shared_page_fini)(linux_shared_page_obj);
__elfN(linux_shared_page_fini)(linux_shared_page_obj,
linux_shared_page_mapping);
}
SYSUNINIT(elf_linux_vdso_uninit, SI_SUB_EXEC, SI_ORDER_FIRST,
linux_vdso_deinstall, NULL);

View File

@ -961,7 +961,8 @@ static void
linux_vdso_deinstall(void *param)
{
__elfN(linux_shared_page_fini)(linux_shared_page_obj);
__elfN(linux_shared_page_fini)(linux_shared_page_obj,
linux_shared_page_mapping);
}
SYSUNINIT(elf_linux_vdso_uninit, SI_SUB_EXEC, SI_ORDER_FIRST,
linux_vdso_deinstall, NULL);

View File

@ -461,7 +461,8 @@ linux_vdso_deinstall(const void *param)
{
LIN_SDT_PROBE0(sysvec, linux_vdso_deinstall, todo);
__elfN(linux_shared_page_fini)(linux_shared_page_obj);
__elfN(linux_shared_page_fini)(linux_shared_page_obj,
linux_shared_page_mapping);
}
SYSUNINIT(elf_linux_vdso_uninit, SI_SUB_EXEC, SI_ORDER_FIRST,
linux_vdso_deinstall, NULL);

View File

@ -93,9 +93,13 @@ __elfN(linux_shared_page_init)(char **mapping)
}
void
__elfN(linux_shared_page_fini)(vm_object_t obj)
__elfN(linux_shared_page_fini)(vm_object_t obj, void *mapping)
{
vm_offset_t va;
va = (vm_offset_t)mapping;
pmap_qremove(va, 1);
kva_free(va, PAGE_SIZE);
vm_object_deallocate(obj);
}

View File

@ -39,7 +39,7 @@ struct linux_vdso_sym {
};
vm_object_t __elfN(linux_shared_page_init)(char **);
void __elfN(linux_shared_page_fini)(vm_object_t);
void __elfN(linux_shared_page_fini)(vm_object_t, void *);
void __elfN(linux_vdso_fixup)(struct sysentvec *);
void __elfN(linux_vdso_reloc)(struct sysentvec *);
void __elfN(linux_vdso_sym_init)(struct linux_vdso_sym *);