[PATCH] mips/vdso: Support mremap() for vDSO
From: Guoyun Sun
Date: Tue Jan 14 2020 - 00:13:53 EST
vDSO VMA address is saved in mm_context for the purpose of using
restorer from vDSO page to return to userspace after signal handling.
In Checkpoint Restore in Userspace (CRIU) project we place vDSO VMA
on restore back to the place where it was on the dump.
Make vDSO code track the VMA address by supplying .mremap() fops
the same way it's done for x86 and arm by:
commit b059a453b1cf ("x86/vdso: Add mremap hook to vm_special_mapping")
commit 739586951b8a ("arm64/vdso: Support mremap() for vDSO").
Signed-off-by: Guoyun Sun <sunguoyun@xxxxxxxxxxx>
---
arch/mips/kernel/vdso.c | 22 ++++++++++++++++++++++
arch/mips/vdso/genvdso.c | 5 +++++
2 files changed, 27 insertions(+)
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index bc35f84..eac3982 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -38,6 +38,28 @@ static struct vm_special_mapping vdso_vvar_mapping = {
.pages = no_pages,
};
+int vdso_mremap(const struct vm_special_mapping *sm,
+ struct vm_area_struct *new_vma)
+{
+ unsigned long new_size = new_vma->vm_end - new_vma->vm_start;
+
+#ifdef CONFIG_MIPS32_O32
+ if (vdso_image_o32.size != new_size)
+ return -EINVAL;
+#endif
+
+#ifdef CONFIG_MIPS32_N32
+ if (vdso_image_n32.size != new_size)
+ return -EINVAL;
+#endif
+
+ if (vdso_image.size != new_size)
+ return -EINVAL;
+
+ current->mm->context.vdso = (void __user *)(new_vma->vm_start);
+ return 0;
+}
+
static void __init init_vdso_image(struct mips_vdso_image *image)
{
unsigned long num_pages, i;
diff --git a/arch/mips/vdso/genvdso.c b/arch/mips/vdso/genvdso.c
index b66b6b1..50ea516 100644
--- a/arch/mips/vdso/genvdso.c
+++ b/arch/mips/vdso/genvdso.c
@@ -251,6 +251,10 @@ int main(int argc, char **argv)
fprintf(out_file, "#include <linux/linkage.h>\n");
fprintf(out_file, "#include <linux/mm.h>\n");
fprintf(out_file, "#include <asm/vdso.h>\n");
+ fprintf(out_file, "\n");
+ fprintf(out_file, "extern int vdso_mremap(\n");
+ fprintf(out_file, " const struct vm_special_mapping *sm,\n");
+ fprintf(out_file, " struct vm_area_struct *new_vma);\n\n");
/* Write out the stripped VDSO data. */
fprintf(out_file,
@@ -275,6 +279,7 @@ int main(int argc, char **argv)
fprintf(out_file, "\t.mapping = {\n");
fprintf(out_file, "\t\t.name = \"[vdso]\",\n");
fprintf(out_file, "\t\t.pages = vdso_pages,\n");
+ fprintf(out_file, "\t\t.mremap = vdso_mremap,\n");
fprintf(out_file, "\t},\n");
/* Calculate and write symbol offsets to <output file> */
--
2.1.0