]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
powerpc/vdso: Fix VDSO data access when running in a non-root time namespace
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Fri, 6 Sep 2024 08:33:43 +0000 (10:33 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Fri, 13 Sep 2024 15:28:36 +0000 (17:28 +0200)
When running in a non-root time namespace, the global VDSO data page
is replaced by a dedicated namespace data page and the global data
page is mapped next to it. Detailed explanations can be found at
commit 660fd04f9317 ("lib/vdso: Prepare for time namespace support").

When it happens, __kernel_get_syscall_map and __kernel_get_tbfreq
and __kernel_sync_dicache don't work anymore because they read 0
instead of the data they need.

To address that, clock_mode has to be read. When it is set to
VDSO_CLOCKMODE_TIMENS, it means it is a dedicated namespace data page
and the global data is located on the following page.

Add a macro called get_realdatapage which reads clock_mode and add
PAGE_SIZE to the pointer provided by get_datapage macro when
clock_mode is equal to VDSO_CLOCKMODE_TIMENS. Use this new macro
instead of get_datapage macro except for time functions as they handle
it internally.

Fixes: 74205b3fc2ef ("powerpc/vdso: Add support for time namespaces")
Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
Closes: https://lore.kernel.org/all/ZtnYqZI-nrsNslwy@zx2c4.com/
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Acked-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
arch/powerpc/include/asm/vdso_datapage.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/vdso/cacheflush.S
arch/powerpc/kernel/vdso/datapage.S

index a585c8e538ff0fe1e422c117ca44abb1d6b7aa3b..939daf6b695ef1e2b84a1be00efcfe4a5a05834a 100644 (file)
@@ -111,6 +111,21 @@ extern struct vdso_arch_data *vdso_data;
        addi    \ptr, \ptr, (_vdso_datapage - 999b)@l
 .endm
 
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+
+.macro get_realdatapage ptr scratch
+       get_datapage \ptr
+#ifdef CONFIG_TIME_NS
+       lwz     \scratch, VDSO_CLOCKMODE_OFFSET(\ptr)
+       xoris   \scratch, \scratch, VDSO_CLOCKMODE_TIMENS@h
+       xori    \scratch, \scratch, VDSO_CLOCKMODE_TIMENS@l
+       cntlzw  \scratch, \scratch
+       rlwinm  \scratch, \scratch, PAGE_SHIFT - 5, 1 << PAGE_SHIFT
+       add     \ptr, \ptr, \scratch
+#endif
+.endm
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 23733282de4d9f975aa9450b26c1049688e6663e..7b3feb6bc2103bc89ea14fbaac6937f1c97d4ff8 100644 (file)
@@ -346,6 +346,8 @@ int main(void)
 #else
        OFFSET(CFG_SYSCALL_MAP32, vdso_arch_data, syscall_map);
 #endif
+       OFFSET(VDSO_CLOCKMODE_OFFSET, vdso_arch_data, data[0].clock_mode);
+       DEFINE(VDSO_CLOCKMODE_TIMENS, VDSO_CLOCKMODE_TIMENS);
 
 #ifdef CONFIG_BUG
        DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
index 0085ae464dac9c32381625a6969a4e422ad34eb7..3b2479bd2f9a1d2e04e8eeb8fbcdff479e953d16 100644 (file)
@@ -30,7 +30,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 #ifdef CONFIG_PPC64
        mflr    r12
   .cfi_register lr,r12
-       get_datapage    r10
+       get_realdatapage        r10, r11
        mtlr    r12
   .cfi_restore lr
 #endif
index db8e167f01667eb95b3dc74f6771e610411bba90..2b19b6201a33a8f4a3b843a85fadc509d4e12788 100644 (file)
@@ -28,7 +28,7 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map)
        mflr    r12
   .cfi_register lr,r12
        mr.     r4,r3
-       get_datapage    r3
+       get_realdatapage        r3, r11
        mtlr    r12
 #ifdef __powerpc64__
        addi    r3,r3,CFG_SYSCALL_MAP64
@@ -52,7 +52,7 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
   .cfi_startproc
        mflr    r12
   .cfi_register lr,r12
-       get_datapage    r3
+       get_realdatapage        r3, r11
 #ifndef __powerpc64__
        lwz     r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
 #endif