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-16 14:40:02 +0000
commit0fc8a796722846d0d676548aa0f5cc660199db73 (patch)
tree80c22249e6f3a176889367dbce00f5da4ae592c6
parent2d936e6c99ad1c4fb01f6c99a96dcc924ee44b9d (diff)
downloadsrc-0fc8a796722846d0d676548aa0f5cc660199db73.tar.gz
src-0fc8a796722846d0d676548aa0f5cc660199db73.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 MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D28696
-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 *);