Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Fix 32-bit frames for signals delivered when transactional

Commit d31626f70b61 ("powerpc: Don't corrupt transactional state when
using FP/VMX in kernel") introduced a bug where the uc_link and uc_regs
fields of the ucontext_t that is created to hold the transactional
values of the registers in a 32-bit signal frame didn't get set
correctly. The reason is that we now clear the MSR_TS bits in the MSR
in save_tm_user_regs(), before the code that sets uc_link and uc_regs.
To fix this, we move the setting of uc_link and uc_regs into the same
if statement that selects whether to call save_tm_user_regs() or
save_user_regs().

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Paul Mackerras and committed by
Benjamin Herrenschmidt
d765ff23 67bfa0ee

+7 -12
+7 -12
arch/powerpc/kernel/signal_32.c
··· 1022 1022 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 1023 1023 tm_frame = &rt_sf->uc_transact.uc_mcontext; 1024 1024 if (MSR_TM_ACTIVE(regs->msr)) { 1025 + if (__put_user((unsigned long)&rt_sf->uc_transact, 1026 + &rt_sf->uc.uc_link) || 1027 + __put_user((unsigned long)tm_frame, 1028 + &rt_sf->uc_transact.uc_regs)) 1029 + goto badframe; 1025 1030 if (save_tm_user_regs(regs, frame, tm_frame, sigret)) 1026 1031 goto badframe; 1027 1032 } 1028 1033 else 1029 1034 #endif 1030 1035 { 1036 + if (__put_user(0, &rt_sf->uc.uc_link)) 1037 + goto badframe; 1031 1038 if (save_user_regs(regs, frame, tm_frame, sigret, 1)) 1032 1039 goto badframe; 1033 1040 } 1034 1041 regs->link = tramp; 1035 - 1036 - #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 1037 - if (MSR_TM_ACTIVE(regs->msr)) { 1038 - if (__put_user((unsigned long)&rt_sf->uc_transact, 1039 - &rt_sf->uc.uc_link) 1040 - || __put_user((unsigned long)tm_frame, &rt_sf->uc_transact.uc_regs)) 1041 - goto badframe; 1042 - } 1043 - else 1044 - #endif 1045 - if (__put_user(0, &rt_sf->uc.uc_link)) 1046 - goto badframe; 1047 1042 1048 1043 current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */ 1049 1044