[PATCH] x86/vdso: Limit vdso allocation to 47-bit address space

From: Marcelina Kościelnicka
Date: Mon May 29 2023 - 09:05:42 EST


The vdso is normally allocated after the stack, with a random offset.
With ADDR_NO_RANDOMIZE and without 57-bit virtual addressing, the stack is
too close to the canonical address hole to fit the vdso after it, so it
reverts to normal mmap handling, resulting in something like the
following (deterministic) address map:

[...]
7ffff7fc4000-7ffff7fc8000 r--p 00000000 00:00 0 [vvar]
7ffff7fc8000-7ffff7fca000 r-xp 00000000 00:00 0 [vdso]
7ffff7fca000-7ffff7fcb000 r--p 00000000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffff7fcb000-7ffff7ff1000 r-xp 00001000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffff7ff1000-7ffff7ffb000 r--p 00027000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffff7ffb000-7ffff7ffd000 r--p 00031000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffff7ffd000-7ffff7fff000 rw-p 00033000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]

However, on a CPU with LA57 support, allocating the vdso after the stack
actually succeeds and results in something like the following:

[...]
7ffff7fca000-7ffff7fcb000 r--p 00000000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffff7fcb000-7ffff7ff1000 r-xp 00001000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffff7ff1000-7ffff7ffb000 r--p 00027000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffff7ffb000-7ffff7ffd000 r--p 00031000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffff7ffd000-7ffff7fff000 rw-p 00033000 fe:01 1183001 /usr/lib/ld-linux-x86-64.so.2
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
8000001be000-8000001c2000 r--p 00000000 00:00 0 [vvar]
8000001c2000-8000001c4000 r-xp 00000000 00:00 0 [vdso]

The resulting map has two problems:

1. The vdso mapping address is non-deterministic, since the
get_random_u32_below call in vdso_addr is called unconditionally,
without taking PF_RANDOMIZE into account.
2. The vdso is mapped outside of the legacy 47-bit address space,
needlessly allocating 4 page tables and violating the principles
outlined in Documentation/x86/x86_64/5level-paging.rst

This patch forces vdso allocation range to always be within the 47-bit
space, ensuring consistent results between LA57 and non-LA57 systems.

Signed-off-by: Marcelina Kościelnicka <mwk@xxxxxxxx>
---
arch/x86/entry/vdso/vma.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 2738eb28cb2e..1f4bdbadae1e 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -301,8 +301,8 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)

/* Round the lowest possible end address up to a PMD boundary. */
end = (start + len + PMD_SIZE - 1) & PMD_MASK;
- if (end >= TASK_SIZE_MAX)
- end = TASK_SIZE_MAX;
+ if (end >= DEFAULT_MAP_WINDOW)
+ end = DEFAULT_MAP_WINDOW;
end -= len;

if (end > start) {
--
2.40.1