Re: [RFC PATCH v1 16/31] ARC: Signal handling

From: Al Viro
Date: Fri Nov 16 2012 - 00:26:26 EST


> + if (insyscall) {
> + /* No handler for syscall: restart it */
> + if (regs->r0 == -ERESTARTNOHAND ||
> + regs->r0 == -ERESTARTSYS || regs->r0 == -ERESTARTNOINTR) {
> + regs->r0 = regs->orig_r0;
> + regs->ret -= 4;
> + } else if (regs->r0 == -ERESTART_RESTARTBLOCK) {
> + regs->r8 = __NR_restart_syscall;
> + regs->ret -= 4;
> + }

What's to prevent double decrement on ->ret if two signals arrive? Note
that e.g. x86 gets away with similar code only because it uses the same
register for syscall number and return value; since none of -ERESTART...
is a valid syscall number, we either won't get into an analog of that code at
all (-ENOSYS is not restart-worthy) or will revert to a value that is
a valid syscall number, so all subsequent do_signal() calls will not hit
that code. This is subtle and unfortunately not spelled out in the
architectures where it is enough.

You need to make sure that after the first restart in_syscall() will be false.
Same ought to be done in sigreturn(), BTW...
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/