Hi Jason,
Le 06/09/2024 à 05:24, Jason A. Donenfeld a écrit :
On Fri, Sep 06, 2024 at 04:48:28AM +0200, Jason A. Donenfeld wrote:
On Thu, Sep 05, 2024 at 10:41:40PM +0200, Jason A. Donenfeld wrote:
On Thu, Sep 05, 2024 at 06:13:29PM +0200, Jason A. Donenfeld wrote:
+/*
- The macro sets two stack frames, one for the caller and one for the callee
- because there are no requirement for the caller to set a stack frame when
- calling VDSO so it may have omitted to set one, especially on PPC64
- */
+.macro cvdso_call funct
- .cfi_startproc
- PPC_STLU r1, -PPC_MIN_STKFRM(r1)
- .cfi_adjust_cfa_offset PPC_MIN_STKFRM
- mflr r0
- PPC_STLU r1, -PPC_MIN_STKFRM(r1)
- .cfi_adjust_cfa_offset PPC_MIN_STKFRM
- PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
- .cfi_rel_offset lr, PPC_MIN_STKFRM + PPC_LR_STKOFF
- get_datapage r8
- addi r8, r8, VDSO_RNG_DATA_OFFSET
- bl CFUNC(DOTSYM(\funct))
- PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
- cmpwi r3, 0
- mtlr r0
- addi r1, r1, 2 * PPC_MIN_STKFRM
- .cfi_restore lr
- .cfi_def_cfa_offset 0
- crclr so
- bgelr+
- crset so
- neg r3, r3
- blr
- .cfi_endproc
+.endm
Can you figure out what's going on and send a fix, which I'll squash into this commit?
This doesn't work, but I wonder if something like it is what we want. I need to head out for the day, but here's what I've got. It's all wrong but might be of interest.
Oh, I just got one small detail wrong before. The below actually works, and uses the same strategy as on arm64.
Let me know if you'd like me to fix up this commit with the below patch, or if you have another way you'd like to go about it.
And here's the much shorter version in assembly, which maybe you prefer. Also works, and is a bit less invasive than the other thing.
diff --git a/arch/powerpc/kernel/vdso/getrandom.S b/arch/powerpc/kernel/vdso/getrandom.S index a957cd2b2b03..070daba2d547 100644 --- a/arch/powerpc/kernel/vdso/getrandom.S +++ b/arch/powerpc/kernel/vdso/getrandom.S @@ -32,6 +32,14 @@ .cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT #endif get_datapage r8 +#ifdef CONFIG_TIME_NS
- lis r10, 0x7fff
- ori r10, r10, 0xffff
- lwz r9, VDSO_DATA_OFFSET + 4(r8)
- cmpw r9, r10
- bne +8
- addi r8, r8, (1 << CONFIG_PAGE_SHIFT)
+#endif addi r8, r8, VDSO_RNG_DATA_OFFSET bl CFUNC(DOTSYM(\funct)) PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
Thanks for looking.
I came to more or less the same solutions thnt you with the following that seems to work:
diff --git a/arch/powerpc/kernel/vdso/vgetrandom.c b/arch/powerpc/kernel/vdso/vgetrandom.c index 5f855d45fb7b..9705344d39d0 100644 --- a/arch/powerpc/kernel/vdso/vgetrandom.c +++ b/arch/powerpc/kernel/vdso/vgetrandom.c @@ -4,11 +4,19 @@ * * Copyright (C) 2024 Christophe Leroy christophe.leroy@csgroup.eu, CS GROUP France */ +#include <linux/container_of.h> #include <linux/time.h> #include <linux/types.h>
+#include <asm/vdso_datapage.h> + ssize_t __c_kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, size_t opaque_len, const struct vdso_rng_data *vd) { + struct vdso_arch_data *arch_data = container_of(vd, struct vdso_arch_data, rng_data); + + if (IS_ENABLED(CONFIG_TIME_NS) && arch_data->data[0].clock_mode == VDSO_CLOCKMODE_TIMENS) + vd = (void *)vd + (1UL << CONFIG_PAGE_SHIFT); + return __cvdso_getrandom_data(vd, buffer, len, flags, opaque_state, opaque_len); }
However, if we have this problem with __kernel_getrandom, don't we also have it with: ? __kernel_get_syscall_map; __kernel_get_tbfreq; __kernel_sync_dicache;
If they are also affected, then get_page macro is the place to fix.
I will check all of this now and keep you updated before noon (Paris Time).
Christophe