aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-02-16 14:30:21 +0000
committerMark Johnston <markj@FreeBSD.org>2021-02-23 01:29:55 +0000
commit3df2766a691679ac383aabc8409a1a84433c15e6 (patch)
tree6b8de7d29ed9fbc6c1f8a1964c53971c54532dcd
parentab3e1bd3c22a222520c23c2793cc39e3a23c9b46 (diff)
downloadsrc-3df2766a691679ac383aabc8409a1a84433c15e6.tar.gz
src-3df2766a691679ac383aabc8409a1a84433c15e6.zip
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 Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D28696 (cherry picked from commit 0fc8a796722846d0d676548aa0f5cc660199db73)
-rw-r--r--sys/amd64/linux/linux_sysvec.c3
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c3
-rw-r--r--sys/arm64/linux/linux_sysvec.c3
-rw-r--r--sys/compat/linux/linux_vdso.c6
-rw-r--r--sys/compat/linux/linux_vdso.h2
5 files changed, 12 insertions, 5 deletions
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
index dbfc650a916e..abc750c63682 100644
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -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);
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index d06a1fb17d9b..bb86baefaec4 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -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);
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
index 366fe7c2dc44..1d628ffe6ecb 100644
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -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);
diff --git a/sys/compat/linux/linux_vdso.c b/sys/compat/linux/linux_vdso.c
index 096f2e424850..a05c0b01ff40 100644
--- a/sys/compat/linux/linux_vdso.c
+++ b/sys/compat/linux/linux_vdso.c
@@ -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);
}
diff --git a/sys/compat/linux/linux_vdso.h b/sys/compat/linux/linux_vdso.h
index 542efef9cb82..073c51696387 100644
--- a/sys/compat/linux/linux_vdso.h
+++ b/sys/compat/linux/linux_vdso.h
@@ -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 *);