VDSO is randomized even when ASLR is disabled

From: Borys Popławski
Date: Tue Feb 01 2022 - 12:12:57 EST


Hello,
I've stumbled upon an issue of VDSO address being randomized on x86_64 when ASLR is disabled. This happens only on systems with 5-level paging enabled. Details below.

Relevant code: "vdso_addr" in arch/x86/entry/vdso/vma.c
VDSO base address is picked at random starting from the stack bottom address so that it stays in the same PMD as the stack. This randomization is made regardless of PF_RANDOMIZE flag.
With ASLR off, stack is mapped at the highest possible address in 4-level paging, which is 0x7ffffffff000 - this leaves no space for VDSO after the stack, which effectively disables the above randomization. With 5-level paging the stack address stays the same, but "TASK_SIZE_MAX" is much greater, allowing for the above randomization.

This behavior is present in all versions (since VDSO was introduced on x64). I think the fix could be as simple as:

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 235a5794296a..0bc83e4ca512 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -326,7 +326,7 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
end = TASK_SIZE_MAX;
end -= len;

- if (end > start) {
+ if (end > start && (current->flags & PF_RANDOMIZE)) {
offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
addr = start + (offset << PAGE_SHIFT);
} else {

but I've not tested it yet, figured I'll post here first.

Best regards,
Borys