diff options
Diffstat (limited to 'arch/s390/kernel/compat_signal.c')
-rw-r--r-- | arch/s390/kernel/compat_signal.c | 102 |
1 files changed, 23 insertions, 79 deletions
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index fa2b3bc22f20..ef706694a0c1 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c | |||
@@ -1,8 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/signal32.c | 2 | * arch/s390/kernel/compat_signal.c |
3 | * | 3 | * |
4 | * S390 version | 4 | * Copyright (C) IBM Corp. 2000,2006 |
5 | * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation | ||
6 | * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) | 5 | * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) |
7 | * Gerhard Tonn (ton@de.ibm.com) | 6 | * Gerhard Tonn (ton@de.ibm.com) |
8 | * | 7 | * |
@@ -52,8 +51,6 @@ typedef struct | |||
52 | struct ucontext32 uc; | 51 | struct ucontext32 uc; |
53 | } rt_sigframe32; | 52 | } rt_sigframe32; |
54 | 53 | ||
55 | asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset)); | ||
56 | |||
57 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | 54 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) |
58 | { | 55 | { |
59 | int err; | 56 | int err; |
@@ -161,66 +158,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | |||
161 | return err; | 158 | return err; |
162 | } | 159 | } |
163 | 160 | ||
164 | /* | ||
165 | * Atomically swap in the new signal mask, and wait for a signal. | ||
166 | */ | ||
167 | asmlinkage int | ||
168 | sys32_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask) | ||
169 | { | ||
170 | sigset_t saveset; | ||
171 | |||
172 | mask &= _BLOCKABLE; | ||
173 | spin_lock_irq(¤t->sighand->siglock); | ||
174 | saveset = current->blocked; | ||
175 | siginitset(¤t->blocked, mask); | ||
176 | recalc_sigpending(); | ||
177 | spin_unlock_irq(¤t->sighand->siglock); | ||
178 | regs->gprs[2] = -EINTR; | ||
179 | |||
180 | while (1) { | ||
181 | set_current_state(TASK_INTERRUPTIBLE); | ||
182 | schedule(); | ||
183 | if (do_signal(regs, &saveset)) | ||
184 | return -EINTR; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | asmlinkage int | ||
189 | sys32_rt_sigsuspend(struct pt_regs * regs, compat_sigset_t __user *unewset, | ||
190 | size_t sigsetsize) | ||
191 | { | ||
192 | sigset_t saveset, newset; | ||
193 | compat_sigset_t set32; | ||
194 | |||
195 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
196 | if (sigsetsize != sizeof(sigset_t)) | ||
197 | return -EINVAL; | ||
198 | |||
199 | if (copy_from_user(&set32, unewset, sizeof(set32))) | ||
200 | return -EFAULT; | ||
201 | switch (_NSIG_WORDS) { | ||
202 | case 4: newset.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32); | ||
203 | case 3: newset.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32); | ||
204 | case 2: newset.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32); | ||
205 | case 1: newset.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32); | ||
206 | } | ||
207 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
208 | |||
209 | spin_lock_irq(¤t->sighand->siglock); | ||
210 | saveset = current->blocked; | ||
211 | current->blocked = newset; | ||
212 | recalc_sigpending(); | ||
213 | spin_unlock_irq(¤t->sighand->siglock); | ||
214 | regs->gprs[2] = -EINTR; | ||
215 | |||
216 | while (1) { | ||
217 | set_current_state(TASK_INTERRUPTIBLE); | ||
218 | schedule(); | ||
219 | if (do_signal(regs, &saveset)) | ||
220 | return -EINTR; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | asmlinkage long | 161 | asmlinkage long |
225 | sys32_sigaction(int sig, const struct old_sigaction32 __user *act, | 162 | sys32_sigaction(int sig, const struct old_sigaction32 __user *act, |
226 | struct old_sigaction32 __user *oact) | 163 | struct old_sigaction32 __user *oact) |
@@ -520,7 +457,7 @@ static inline int map_signal(int sig) | |||
520 | return sig; | 457 | return sig; |
521 | } | 458 | } |
522 | 459 | ||
523 | static void setup_frame32(int sig, struct k_sigaction *ka, | 460 | static int setup_frame32(int sig, struct k_sigaction *ka, |
524 | sigset_t *set, struct pt_regs * regs) | 461 | sigset_t *set, struct pt_regs * regs) |
525 | { | 462 | { |
526 | sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32)); | 463 | sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32)); |
@@ -565,13 +502,14 @@ static void setup_frame32(int sig, struct k_sigaction *ka, | |||
565 | /* Place signal number on stack to allow backtrace from handler. */ | 502 | /* Place signal number on stack to allow backtrace from handler. */ |
566 | if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) | 503 | if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) |
567 | goto give_sigsegv; | 504 | goto give_sigsegv; |
568 | return; | 505 | return 0; |
569 | 506 | ||
570 | give_sigsegv: | 507 | give_sigsegv: |
571 | force_sigsegv(sig, current); | 508 | force_sigsegv(sig, current); |
509 | return -EFAULT; | ||
572 | } | 510 | } |
573 | 511 | ||
574 | static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, | 512 | static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, |
575 | sigset_t *set, struct pt_regs * regs) | 513 | sigset_t *set, struct pt_regs * regs) |
576 | { | 514 | { |
577 | int err = 0; | 515 | int err = 0; |
@@ -615,31 +553,37 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
615 | regs->gprs[2] = map_signal(sig); | 553 | regs->gprs[2] = map_signal(sig); |
616 | regs->gprs[3] = (__u64) &frame->info; | 554 | regs->gprs[3] = (__u64) &frame->info; |
617 | regs->gprs[4] = (__u64) &frame->uc; | 555 | regs->gprs[4] = (__u64) &frame->uc; |
618 | return; | 556 | return 0; |
619 | 557 | ||
620 | give_sigsegv: | 558 | give_sigsegv: |
621 | force_sigsegv(sig, current); | 559 | force_sigsegv(sig, current); |
560 | return -EFAULT; | ||
622 | } | 561 | } |
623 | 562 | ||
624 | /* | 563 | /* |
625 | * OK, we're invoking a handler | 564 | * OK, we're invoking a handler |
626 | */ | 565 | */ |
627 | 566 | ||
628 | void | 567 | int |
629 | handle_signal32(unsigned long sig, struct k_sigaction *ka, | 568 | handle_signal32(unsigned long sig, struct k_sigaction *ka, |
630 | siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) | 569 | siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) |
631 | { | 570 | { |
571 | int ret; | ||
572 | |||
632 | /* Set up the stack frame */ | 573 | /* Set up the stack frame */ |
633 | if (ka->sa.sa_flags & SA_SIGINFO) | 574 | if (ka->sa.sa_flags & SA_SIGINFO) |
634 | setup_rt_frame32(sig, ka, info, oldset, regs); | 575 | ret = setup_rt_frame32(sig, ka, info, oldset, regs); |
635 | else | 576 | else |
636 | setup_frame32(sig, ka, oldset, regs); | 577 | ret = setup_frame32(sig, ka, oldset, regs); |
637 | 578 | ||
638 | spin_lock_irq(¤t->sighand->siglock); | 579 | if (ret == 0) { |
639 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 580 | spin_lock_irq(¤t->sighand->siglock); |
640 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 581 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); |
641 | sigaddset(¤t->blocked,sig); | 582 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
642 | recalc_sigpending(); | 583 | sigaddset(¤t->blocked,sig); |
643 | spin_unlock_irq(¤t->sighand->siglock); | 584 | recalc_sigpending(); |
585 | spin_unlock_irq(¤t->sighand->siglock); | ||
586 | } | ||
587 | return ret; | ||
644 | } | 588 | } |
645 | 589 | ||