On Wed, Nov 08, 2017 at 01:55:05PM +0800, Greentime Hu wrote: > +static int restore_sigframe(struct pt_regs *regs, > + struct rt_sigframe __user * sf) > +{ [snip] > + err |= !valid_user_regs(regs); IDGI... Where do you modify ->ipsw at all and how can valid_user_regs() come to be false here? > +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) > +{ > + struct rt_sigframe __user *frame; > + > + /* Always make any pending restarted system calls return -EINTR */ > + current->restart_block.fn = do_no_restart_syscall; > + > + /* > + * Since we stacked the signal on a 64-bit boundary, > + * then 'sp' should be two-word aligned here. If it's > + * not, then the user is trying to mess with us. > + */ > + if (regs->sp & 7) > + goto badframe; > + > + frame = (struct rt_sigframe __user *)regs->sp; > + > + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) > + goto badframe; > + > + if (restore_sigframe(regs, frame)) > + goto badframe; > + > + if (restore_altstack(&frame->uc.uc_stack)) > + goto badframe; > + > + return regs->uregs[0]; > + > +badframe: > + force_sig(SIGSEGV, current); > + return 0; > +} AFAICS, you are copying arm; take a good look at sys_rt_sigreturn_wrapper there - specifically, the 'mov why, #0' part. Consider what happens if you get an interrupt at the moment when $r0 contains -ERESTARTSYS (for example) and signal arrives while we are processing the interrupt. It will be handled on the way out, without any syscall restart crap ('why' is 0 on that codepath). So far, so good, but think what'll happen when you are done with the signal handler. sigreturn() is called, the values we had stashed in sigcontext go back into registers (OK, pt_regs on kernel stack that will be used to reload the registers on return to userland)... and the signals that had been blocked for the duration of handlers (see sa_mask in sigaction(2)) get unblocked. And it turns out that you have one of those pending - it had arrived while we'd been in the handler. Now we are fucked. You have TIF_SIGPENDING set, so do_notify_resume() is called. And everything looks exactly as if you had a syscall restart situation - regs->uregs[0] being one of -ERESTART... and 'syscall' flag being true. So we go into the second signal handler (as we ought to) with saved ->ipc set 4 bytes back from where we were going to return. It would've been the right thing to do if it *was* a syscall restart, but we were returning to the location where the original interrupt had caught us. Result: with the right timing, an interrupt arriving when userland process has $r0 equal -512 may lead to instruction pointer jumping 4 bytes back. Pity the poor sod trying to debug that kind of breakage... Restart should *NOT* be triggered upon sigreturn(2). > +static int > +setup_return(struct pt_regs *regs, struct ksignal *ksig, void __user * frame) > +{ > + unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler; > + unsigned long retcode; > + > + /* > + * Maybe we need to deliver a 32-bit signal to a 26-bit task. Deliver to what, again? That comment made sense (if rather sad one) on arm, but what is it doing here? > +static int do_signal(struct pt_regs *regs, int syscall) > +{ > + unsigned int retval = 0, continue_addr = 0, restart_addr = 0; > + struct ksignal ksig; > + int restart = 0; > + > + /* > + * We want the common case to go fast, which > + * is why we may in certain cases get here from > + * kernel mode. Just return without doing anything > + * if so. > + */ > + if (!user_mode(regs)) > + return 0; Which cases would those be?