Commit 392fb6e35400edbee183baba24b34a0fa2053813
Committed by
Matt Turner
1 parent
2deba1bd71
Exists in
master
and in
4 other branches
alpha: unb0rk sigsuspend() and rt_sigsuspend()
Old code used to set regs->r0 and regs->r19 to force the right return value. Leaving that after switch to ERESTARTNOHAND was a Bad Idea(tm), since now that screws the restart - if we hit the case when get_signal_to_deliver() returns 0, we will step back to syscall insn, with v0 set to EINTR and a3 to 1. The latter won't matter, since EINTR is 4, aka __NR_write. Testcase: #include <signal.h> #define _GNU_SOURCE #include <unistd.h> #include <sys/syscall.h> main() { sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCONT); sigprocmask(SIG_SETMASK, &mask, NULL); kill(0, SIGCONT); syscall(__NR_sigsuspend, 1, "b0rken\n", 7); } results on alpha in immediate message to stdout... Fix is obvious; moreover, since we don't need regs anymore, we can switch to normal prototypes for these guys and lose the wrappers. Even better, rt_sigsuspend() is identical to generic version in kernel/signal.c now. Tested-by: Michael Cree <mcree@orcon.net.nz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Matt Turner <mattst88@gmail.com>
Showing 3 changed files with 2 additions and 69 deletions Side-by-side Diff
arch/alpha/include/asm/unistd.h
arch/alpha/kernel/entry.S
... | ... | @@ -779,38 +779,6 @@ |
779 | 779 | .end sys_rt_sigreturn |
780 | 780 | |
781 | 781 | .align 4 |
782 | - .globl sys_sigsuspend | |
783 | - .ent sys_sigsuspend | |
784 | -sys_sigsuspend: | |
785 | - .prologue 0 | |
786 | - mov $sp, $17 | |
787 | - br $1, do_switch_stack | |
788 | - mov $sp, $18 | |
789 | - subq $sp, 16, $sp | |
790 | - stq $26, 0($sp) | |
791 | - jsr $26, do_sigsuspend | |
792 | - ldq $26, 0($sp) | |
793 | - lda $sp, SWITCH_STACK_SIZE+16($sp) | |
794 | - ret | |
795 | -.end sys_sigsuspend | |
796 | - | |
797 | - .align 4 | |
798 | - .globl sys_rt_sigsuspend | |
799 | - .ent sys_rt_sigsuspend | |
800 | -sys_rt_sigsuspend: | |
801 | - .prologue 0 | |
802 | - mov $sp, $18 | |
803 | - br $1, do_switch_stack | |
804 | - mov $sp, $19 | |
805 | - subq $sp, 16, $sp | |
806 | - stq $26, 0($sp) | |
807 | - jsr $26, do_rt_sigsuspend | |
808 | - ldq $26, 0($sp) | |
809 | - lda $sp, SWITCH_STACK_SIZE+16($sp) | |
810 | - ret | |
811 | -.end sys_rt_sigsuspend | |
812 | - | |
813 | - .align 4 | |
814 | 782 | .globl sys_sethae |
815 | 783 | .ent sys_sethae |
816 | 784 | sys_sethae: |
arch/alpha/kernel/signal.c
... | ... | @@ -144,8 +144,7 @@ |
144 | 144 | /* |
145 | 145 | * Atomically swap in the new signal mask, and wait for a signal. |
146 | 146 | */ |
147 | -asmlinkage int | |
148 | -do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) | |
147 | +SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) | |
149 | 148 | { |
150 | 149 | mask &= _BLOCKABLE; |
151 | 150 | spin_lock_irq(¤t->sighand->siglock); |
... | ... | @@ -153,41 +152,6 @@ |
153 | 152 | siginitset(¤t->blocked, mask); |
154 | 153 | recalc_sigpending(); |
155 | 154 | spin_unlock_irq(¤t->sighand->siglock); |
156 | - | |
157 | - /* Indicate EINTR on return from any possible signal handler, | |
158 | - which will not come back through here, but via sigreturn. */ | |
159 | - regs->r0 = EINTR; | |
160 | - regs->r19 = 1; | |
161 | - | |
162 | - current->state = TASK_INTERRUPTIBLE; | |
163 | - schedule(); | |
164 | - set_thread_flag(TIF_RESTORE_SIGMASK); | |
165 | - return -ERESTARTNOHAND; | |
166 | -} | |
167 | - | |
168 | -asmlinkage int | |
169 | -do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, | |
170 | - struct pt_regs *regs, struct switch_stack *sw) | |
171 | -{ | |
172 | - sigset_t set; | |
173 | - | |
174 | - /* XXX: Don't preclude handling different sized sigset_t's. */ | |
175 | - if (sigsetsize != sizeof(sigset_t)) | |
176 | - return -EINVAL; | |
177 | - if (copy_from_user(&set, uset, sizeof(set))) | |
178 | - return -EFAULT; | |
179 | - | |
180 | - sigdelsetmask(&set, ~_BLOCKABLE); | |
181 | - spin_lock_irq(¤t->sighand->siglock); | |
182 | - current->saved_sigmask = current->blocked; | |
183 | - current->blocked = set; | |
184 | - recalc_sigpending(); | |
185 | - spin_unlock_irq(¤t->sighand->siglock); | |
186 | - | |
187 | - /* Indicate EINTR on return from any possible signal handler, | |
188 | - which will not come back through here, but via sigreturn. */ | |
189 | - regs->r0 = EINTR; | |
190 | - regs->r19 = 1; | |
191 | 155 | |
192 | 156 | current->state = TASK_INTERRUPTIBLE; |
193 | 157 | schedule(); |