Skip to content

Commit 5499802

Browse files
chleroympe
authored andcommitted
powerpc/signal32: Fix sigset_t copy
The conversion from __copy_from_user() to __get_user() by commit d3ccc97 ("powerpc/signal: Use __get_user() to copy sigset_t") introduced a regression in __get_user_sigset() for powerpc/32. The bug was subsequently moved into unsafe_get_user_sigset(). The bug is due to the copied 64 bit value being truncated to 32 bits while being assigned to dst->sig[0] The regression was reported by users of the Xorg packages distributed in Debian/powerpc -- "The symptoms are that the fb screen goes blank, with the backlight remaining on and no errors logged in /var/log; wdm (or startx) run with no effect (I tried logging in in the blind, with no effect). And they are hard to kill, requiring 'kill -KILL ...'" Fix the regression by copying each word of the sigset, not only the first one. __get_user_sigset() was tentatively optimised to copy 64 bits at once in order to minimise KUAP unlock/lock impact, but the unsafe variant doesn't suffer that, so it can just copy words. Fixes: 887f3ce ("powerpc/signal32: Convert do_setcontext[_tm]() to user access block") Cc: [email protected] # v5.13+ Reported-by: Finn Thain <[email protected]> Reported-and-tested-by: Stan Johnson <[email protected]> Signed-off-by: Christophe Leroy <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/99ef38d61c0eb3f79c68942deb0c35995a93a777.1636966353.git.christophe.leroy@csgroup.eu
1 parent 5b54860 commit 5499802

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

arch/powerpc/kernel/signal.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,14 @@ static inline int __get_user_sigset(sigset_t *dst, const sigset_t __user *src)
2525

2626
return __get_user(dst->sig[0], (u64 __user *)&src->sig[0]);
2727
}
28-
#define unsafe_get_user_sigset(dst, src, label) \
29-
unsafe_get_user((dst)->sig[0], (u64 __user *)&(src)->sig[0], label)
28+
#define unsafe_get_user_sigset(dst, src, label) do { \
29+
sigset_t *__dst = dst; \
30+
const sigset_t __user *__src = src; \
31+
int i; \
32+
\
33+
for (i = 0; i < _NSIG_WORDS; i++) \
34+
unsafe_get_user(__dst->sig[i], &__src->sig[i], label); \
35+
} while (0)
3036

3137
#ifdef CONFIG_VSX
3238
extern unsigned long copy_vsx_to_user(void __user *to,

0 commit comments

Comments
 (0)