From 41cd81abafdc4e58a93fcb677712a76885e3ca25 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Wed, 6 Apr 2022 09:17:21 +0200 Subject: [PATCH] s390/vdso: add vdso randomization Randomize the address of vdso if randomize_va_space is enabled. Note that this keeps the vdso address on the same PMD as the stack to avoid allocating an extra page table just for vdso. Signed-off-by: Sven Schnelle Reviewed-by: Heiko Carstens Signed-off-by: Heiko Carstens --- arch/s390/kernel/vdso.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 7ba84a8..5075cde 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -208,6 +209,31 @@ out: return rc; } +static unsigned long vdso_addr(unsigned long start, unsigned long len) +{ + unsigned long addr, end, offset; + + /* + * Round up the start address. It can start out unaligned as a result + * of stack start randomization. + */ + start = PAGE_ALIGN(start); + + /* Round the lowest possible end address up to a PMD boundary. */ + end = (start + len + PMD_SIZE - 1) & PMD_MASK; + if (end >= VDSO_BASE) + end = VDSO_BASE; + end -= len; + + if (end > start) { + offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1); + addr = start + (offset << PAGE_SHIFT); + } else { + addr = start; + } + return addr; +} + unsigned long vdso_size(void) { unsigned long size = VVAR_NR_PAGES * PAGE_SIZE; @@ -221,7 +247,12 @@ unsigned long vdso_size(void) int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { - return map_vdso(VDSO_BASE, vdso_size()); + unsigned long addr = VDSO_BASE; + unsigned long size = vdso_size(); + + if (current->flags & PF_RANDOMIZE) + addr = vdso_addr(current->mm->start_stack + PAGE_SIZE, size); + return map_vdso(addr, size); } static struct page ** __init vdso_setup_pages(void *start, void *end) -- 2.7.4