Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit 4188b15

Browse files
vineetgarcgregkh
authored andcommitted
ARC: SA_SIGINFO ucontext regs off-by-one
commit 6914e1e upstream. The regfile provided to SA_SIGINFO signal handler as ucontext was off by one due to pt_regs gutter cleanups in 2013. Before handling signal, user pt_regs are copied onto user_regs_struct and copied back later. Both structs are binary compatible. This was all fine until commit 2fa9190 (ARC: pt_regs update #2) which removed the empty stack slot at top of pt_regs (corresponding to first pad) and made the corresponding fixup in struct user_regs_struct (the pad in there was moved out of @scratch - not removed altogether as it is part of ptrace ABI) struct user_regs_struct { + long pad; struct { - long pad; long bta, lp_start, lp_end,.... } scratch; ... } This meant that now user_regs_struct was off by 1 reg w.r.t pt_regs and signal code needs to user_regs_struct.scratch to reflect it as pt_regs, which is what this commit does. This problem was hidden for 2 years, because both save/restore, despite using wrong location, were using the same location. Only an interim inspection (reproducer below) exposed the issue. void handle_segv(int signo, siginfo_t *info, void *context) { ucontext_t *uc = context; struct user_regs_struct *regs = &(uc->uc_mcontext.regs); printf("regs %x %x\n", <=== prints 7 8 (vs. 8 9) regs->scratch.r8, regs->scratch.r9); } int main() { struct sigaction sa; sa.sa_sigaction = handle_segv; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, NULL); asm volatile( "mov r7, 7 \n" "mov r8, 8 \n" "mov r9, 9 \n" "mov r10, 10 \n" :::"r7","r8","r9","r10"); *((unsigned int*)0x10) = 0; } Fixes: 2fa9190 "ARC: pt_regs update #2: Remove unused gutter at start of pt_regs" Signed-off-by: Vineet Gupta <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2a4188f commit 4188b15

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

Diff for: arch/arc/kernel/signal.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
6767
sigset_t *set)
6868
{
6969
int err;
70-
err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs,
70+
err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), regs,
7171
sizeof(sf->uc.uc_mcontext.regs.scratch));
7272
err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));
7373

@@ -83,7 +83,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
8383
if (!err)
8484
set_current_blocked(&set);
8585

86-
err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs),
86+
err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs.scratch),
8787
sizeof(sf->uc.uc_mcontext.regs.scratch));
8888

8989
return err;

0 commit comments

Comments
 (0)