Commit c7304938 authored by Christophe Leroy's avatar Christophe Leroy Committed by Jason A. Donenfeld
Browse files

powerpc/vdso: Fix VDSO data access when running in a non-root time namespace



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 660fd04f ("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: 74205b3f ("powerpc/vdso: Add support for time namespaces")
Reported-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
Closes: https://lore.kernel.org/all/ZtnYqZI-nrsNslwy@zx2c4.com/


Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Acked-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
parent 8bc7c5e5
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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__ */
+2 −0
Original line number Diff line number Diff line
@@ -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));
+1 −1
Original line number Diff line number Diff line
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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