diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 21:50:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 21:50:11 -0500 |
commit | 9e2d59ad580d590134285f361a0e80f0e98c0207 (patch) | |
tree | f3232be75781484193413f32ec82c21f6d8eb76e /kernel/signal.c | |
parent | 5ce1a70e2f00f0bce0cab57f798ca354b9496169 (diff) | |
parent | 235b80226b986dabcbba844968f7807866bd0bfe (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull signal handling cleanups from Al Viro:
"This is the first pile; another one will come a bit later and will
contain SYSCALL_DEFINE-related patches.
- a bunch of signal-related syscalls (both native and compat)
unified.
- a bunch of compat syscalls switched to COMPAT_SYSCALL_DEFINE
(fixing several potential problems with missing argument
validation, while we are at it)
- a lot of now-pointless wrappers killed
- a couple of architectures (cris and hexagon) forgot to save
altstack settings into sigframe, even though they used the
(uninitialized) values in sigreturn; fixed.
- microblaze fixes for delivery of multiple signals arriving at once
- saner set of helpers for signal delivery introduced, several
architectures switched to using those."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (143 commits)
x86: convert to ksignal
sparc: convert to ksignal
arm: switch to struct ksignal * passing
alpha: pass k_sigaction and siginfo_t using ksignal pointer
burying unused conditionals
make do_sigaltstack() static
arm64: switch to generic old sigaction() (compat-only)
arm64: switch to generic compat rt_sigaction()
arm64: switch compat to generic old sigsuspend
arm64: switch to generic compat rt_sigqueueinfo()
arm64: switch to generic compat rt_sigpending()
arm64: switch to generic compat rt_sigprocmask()
arm64: switch to generic sigaltstack
sparc: switch to generic old sigsuspend
sparc: COMPAT_SYSCALL_DEFINE does all sign-extension as well as SYSCALL_DEFINE
sparc: kill sign-extending wrappers for native syscalls
kill sparc32_open()
sparc: switch to use of generic old sigaction
sparc: switch sys_compat_rt_sigaction() to COMPAT_SYSCALL_DEFINE
mips: switch to generic sys_fork() and sys_clone()
...
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 332 |
1 files changed, 293 insertions, 39 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 7f82adbad480..2a7ae2963185 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -2399,6 +2399,15 @@ void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, | |||
2399 | tracehook_signal_handler(sig, info, ka, regs, stepping); | 2399 | tracehook_signal_handler(sig, info, ka, regs, stepping); |
2400 | } | 2400 | } |
2401 | 2401 | ||
2402 | void signal_setup_done(int failed, struct ksignal *ksig, int stepping) | ||
2403 | { | ||
2404 | if (failed) | ||
2405 | force_sigsegv(ksig->sig, current); | ||
2406 | else | ||
2407 | signal_delivered(ksig->sig, &ksig->info, &ksig->ka, | ||
2408 | signal_pt_regs(), stepping); | ||
2409 | } | ||
2410 | |||
2402 | /* | 2411 | /* |
2403 | * It could be that complete_signal() picked us to notify about the | 2412 | * It could be that complete_signal() picked us to notify about the |
2404 | * group-wide signal. Other threads should be notified now to take | 2413 | * group-wide signal. Other threads should be notified now to take |
@@ -2616,28 +2625,58 @@ SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, nset, | |||
2616 | return 0; | 2625 | return 0; |
2617 | } | 2626 | } |
2618 | 2627 | ||
2619 | long do_sigpending(void __user *set, unsigned long sigsetsize) | 2628 | #ifdef CONFIG_COMPAT |
2629 | COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, | ||
2630 | compat_sigset_t __user *, oset, compat_size_t, sigsetsize) | ||
2620 | { | 2631 | { |
2621 | long error = -EINVAL; | 2632 | #ifdef __BIG_ENDIAN |
2622 | sigset_t pending; | 2633 | sigset_t old_set = current->blocked; |
2634 | |||
2635 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
2636 | if (sigsetsize != sizeof(sigset_t)) | ||
2637 | return -EINVAL; | ||
2638 | |||
2639 | if (nset) { | ||
2640 | compat_sigset_t new32; | ||
2641 | sigset_t new_set; | ||
2642 | int error; | ||
2643 | if (copy_from_user(&new32, nset, sizeof(compat_sigset_t))) | ||
2644 | return -EFAULT; | ||
2645 | |||
2646 | sigset_from_compat(&new_set, &new32); | ||
2647 | sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); | ||
2648 | |||
2649 | error = sigprocmask(how, &new_set, NULL); | ||
2650 | if (error) | ||
2651 | return error; | ||
2652 | } | ||
2653 | if (oset) { | ||
2654 | compat_sigset_t old32; | ||
2655 | sigset_to_compat(&old32, &old_set); | ||
2656 | if (copy_to_user(oset, &old_set, sizeof(sigset_t))) | ||
2657 | return -EFAULT; | ||
2658 | } | ||
2659 | return 0; | ||
2660 | #else | ||
2661 | return sys_rt_sigprocmask(how, (sigset_t __user *)nset, | ||
2662 | (sigset_t __user *)oset, sigsetsize); | ||
2663 | #endif | ||
2664 | } | ||
2665 | #endif | ||
2623 | 2666 | ||
2667 | static int do_sigpending(void *set, unsigned long sigsetsize) | ||
2668 | { | ||
2624 | if (sigsetsize > sizeof(sigset_t)) | 2669 | if (sigsetsize > sizeof(sigset_t)) |
2625 | goto out; | 2670 | return -EINVAL; |
2626 | 2671 | ||
2627 | spin_lock_irq(¤t->sighand->siglock); | 2672 | spin_lock_irq(¤t->sighand->siglock); |
2628 | sigorsets(&pending, ¤t->pending.signal, | 2673 | sigorsets(set, ¤t->pending.signal, |
2629 | ¤t->signal->shared_pending.signal); | 2674 | ¤t->signal->shared_pending.signal); |
2630 | spin_unlock_irq(¤t->sighand->siglock); | 2675 | spin_unlock_irq(¤t->sighand->siglock); |
2631 | 2676 | ||
2632 | /* Outside the lock because only this thread touches it. */ | 2677 | /* Outside the lock because only this thread touches it. */ |
2633 | sigandsets(&pending, ¤t->blocked, &pending); | 2678 | sigandsets(set, ¤t->blocked, set); |
2634 | 2679 | return 0; | |
2635 | error = -EFAULT; | ||
2636 | if (!copy_to_user(set, &pending, sigsetsize)) | ||
2637 | error = 0; | ||
2638 | |||
2639 | out: | ||
2640 | return error; | ||
2641 | } | 2680 | } |
2642 | 2681 | ||
2643 | /** | 2682 | /** |
@@ -2646,10 +2685,35 @@ out: | |||
2646 | * @set: stores pending signals | 2685 | * @set: stores pending signals |
2647 | * @sigsetsize: size of sigset_t type or larger | 2686 | * @sigsetsize: size of sigset_t type or larger |
2648 | */ | 2687 | */ |
2649 | SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, set, size_t, sigsetsize) | 2688 | SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize) |
2650 | { | 2689 | { |
2651 | return do_sigpending(set, sigsetsize); | 2690 | sigset_t set; |
2691 | int err = do_sigpending(&set, sigsetsize); | ||
2692 | if (!err && copy_to_user(uset, &set, sigsetsize)) | ||
2693 | err = -EFAULT; | ||
2694 | return err; | ||
2695 | } | ||
2696 | |||
2697 | #ifdef CONFIG_COMPAT | ||
2698 | COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, | ||
2699 | compat_size_t, sigsetsize) | ||
2700 | { | ||
2701 | #ifdef __BIG_ENDIAN | ||
2702 | sigset_t set; | ||
2703 | int err = do_sigpending(&set, sigsetsize); | ||
2704 | if (!err) { | ||
2705 | compat_sigset_t set32; | ||
2706 | sigset_to_compat(&set32, &set); | ||
2707 | /* we can get here only if sigsetsize <= sizeof(set) */ | ||
2708 | if (copy_to_user(uset, &set32, sigsetsize)) | ||
2709 | err = -EFAULT; | ||
2710 | } | ||
2711 | return err; | ||
2712 | #else | ||
2713 | return sys_rt_sigpending((sigset_t __user *)uset, sigsetsize); | ||
2714 | #endif | ||
2652 | } | 2715 | } |
2716 | #endif | ||
2653 | 2717 | ||
2654 | #ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER | 2718 | #ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER |
2655 | 2719 | ||
@@ -2927,6 +2991,22 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int, sig) | |||
2927 | return do_tkill(0, pid, sig); | 2991 | return do_tkill(0, pid, sig); |
2928 | } | 2992 | } |
2929 | 2993 | ||
2994 | static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info) | ||
2995 | { | ||
2996 | /* Not even root can pretend to send signals from the kernel. | ||
2997 | * Nor can they impersonate a kill()/tgkill(), which adds source info. | ||
2998 | */ | ||
2999 | if (info->si_code >= 0 || info->si_code == SI_TKILL) { | ||
3000 | /* We used to allow any < 0 si_code */ | ||
3001 | WARN_ON_ONCE(info->si_code < 0); | ||
3002 | return -EPERM; | ||
3003 | } | ||
3004 | info->si_signo = sig; | ||
3005 | |||
3006 | /* POSIX.1b doesn't mention process groups. */ | ||
3007 | return kill_proc_info(sig, info, pid); | ||
3008 | } | ||
3009 | |||
2930 | /** | 3010 | /** |
2931 | * sys_rt_sigqueueinfo - send signal information to a signal | 3011 | * sys_rt_sigqueueinfo - send signal information to a signal |
2932 | * @pid: the PID of the thread | 3012 | * @pid: the PID of the thread |
@@ -2937,25 +3017,26 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig, | |||
2937 | siginfo_t __user *, uinfo) | 3017 | siginfo_t __user *, uinfo) |
2938 | { | 3018 | { |
2939 | siginfo_t info; | 3019 | siginfo_t info; |
2940 | |||
2941 | if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) | 3020 | if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) |
2942 | return -EFAULT; | 3021 | return -EFAULT; |
3022 | return do_rt_sigqueueinfo(pid, sig, &info); | ||
3023 | } | ||
2943 | 3024 | ||
2944 | /* Not even root can pretend to send signals from the kernel. | 3025 | #ifdef CONFIG_COMPAT |
2945 | * Nor can they impersonate a kill()/tgkill(), which adds source info. | 3026 | COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo, |
2946 | */ | 3027 | compat_pid_t, pid, |
2947 | if (info.si_code >= 0 || info.si_code == SI_TKILL) { | 3028 | int, sig, |
2948 | /* We used to allow any < 0 si_code */ | 3029 | struct compat_siginfo __user *, uinfo) |
2949 | WARN_ON_ONCE(info.si_code < 0); | 3030 | { |
2950 | return -EPERM; | 3031 | siginfo_t info; |
2951 | } | 3032 | int ret = copy_siginfo_from_user32(&info, uinfo); |
2952 | info.si_signo = sig; | 3033 | if (unlikely(ret)) |
2953 | 3034 | return ret; | |
2954 | /* POSIX.1b doesn't mention process groups. */ | 3035 | return do_rt_sigqueueinfo(pid, sig, &info); |
2955 | return kill_proc_info(sig, &info, pid); | ||
2956 | } | 3036 | } |
3037 | #endif | ||
2957 | 3038 | ||
2958 | long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) | 3039 | static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) |
2959 | { | 3040 | { |
2960 | /* This is only valid for single tasks */ | 3041 | /* This is only valid for single tasks */ |
2961 | if (pid <= 0 || tgid <= 0) | 3042 | if (pid <= 0 || tgid <= 0) |
@@ -2985,6 +3066,21 @@ SYSCALL_DEFINE4(rt_tgsigqueueinfo, pid_t, tgid, pid_t, pid, int, sig, | |||
2985 | return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); | 3066 | return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); |
2986 | } | 3067 | } |
2987 | 3068 | ||
3069 | #ifdef CONFIG_COMPAT | ||
3070 | COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo, | ||
3071 | compat_pid_t, tgid, | ||
3072 | compat_pid_t, pid, | ||
3073 | int, sig, | ||
3074 | struct compat_siginfo __user *, uinfo) | ||
3075 | { | ||
3076 | siginfo_t info; | ||
3077 | |||
3078 | if (copy_siginfo_from_user32(&info, uinfo)) | ||
3079 | return -EFAULT; | ||
3080 | return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); | ||
3081 | } | ||
3082 | #endif | ||
3083 | |||
2988 | int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) | 3084 | int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) |
2989 | { | 3085 | { |
2990 | struct task_struct *t = current; | 3086 | struct task_struct *t = current; |
@@ -3030,7 +3126,7 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) | |||
3030 | return 0; | 3126 | return 0; |
3031 | } | 3127 | } |
3032 | 3128 | ||
3033 | int | 3129 | static int |
3034 | do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp) | 3130 | do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp) |
3035 | { | 3131 | { |
3036 | stack_t oss; | 3132 | stack_t oss; |
@@ -3095,12 +3191,10 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s | |||
3095 | out: | 3191 | out: |
3096 | return error; | 3192 | return error; |
3097 | } | 3193 | } |
3098 | #ifdef CONFIG_GENERIC_SIGALTSTACK | ||
3099 | SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) | 3194 | SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) |
3100 | { | 3195 | { |
3101 | return do_sigaltstack(uss, uoss, current_user_stack_pointer()); | 3196 | return do_sigaltstack(uss, uoss, current_user_stack_pointer()); |
3102 | } | 3197 | } |
3103 | #endif | ||
3104 | 3198 | ||
3105 | int restore_altstack(const stack_t __user *uss) | 3199 | int restore_altstack(const stack_t __user *uss) |
3106 | { | 3200 | { |
@@ -3118,7 +3212,6 @@ int __save_altstack(stack_t __user *uss, unsigned long sp) | |||
3118 | } | 3212 | } |
3119 | 3213 | ||
3120 | #ifdef CONFIG_COMPAT | 3214 | #ifdef CONFIG_COMPAT |
3121 | #ifdef CONFIG_GENERIC_SIGALTSTACK | ||
3122 | COMPAT_SYSCALL_DEFINE2(sigaltstack, | 3215 | COMPAT_SYSCALL_DEFINE2(sigaltstack, |
3123 | const compat_stack_t __user *, uss_ptr, | 3216 | const compat_stack_t __user *, uss_ptr, |
3124 | compat_stack_t __user *, uoss_ptr) | 3217 | compat_stack_t __user *, uoss_ptr) |
@@ -3168,7 +3261,6 @@ int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp) | |||
3168 | __put_user(t->sas_ss_size, &uss->ss_size); | 3261 | __put_user(t->sas_ss_size, &uss->ss_size); |
3169 | } | 3262 | } |
3170 | #endif | 3263 | #endif |
3171 | #endif | ||
3172 | 3264 | ||
3173 | #ifdef __ARCH_WANT_SYS_SIGPENDING | 3265 | #ifdef __ARCH_WANT_SYS_SIGPENDING |
3174 | 3266 | ||
@@ -3178,7 +3270,7 @@ int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp) | |||
3178 | */ | 3270 | */ |
3179 | SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set) | 3271 | SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set) |
3180 | { | 3272 | { |
3181 | return do_sigpending(set, sizeof(*set)); | 3273 | return sys_rt_sigpending((sigset_t __user *)set, sizeof(old_sigset_t)); |
3182 | } | 3274 | } |
3183 | 3275 | ||
3184 | #endif | 3276 | #endif |
@@ -3234,7 +3326,7 @@ SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset, | |||
3234 | } | 3326 | } |
3235 | #endif /* __ARCH_WANT_SYS_SIGPROCMASK */ | 3327 | #endif /* __ARCH_WANT_SYS_SIGPROCMASK */ |
3236 | 3328 | ||
3237 | #ifdef __ARCH_WANT_SYS_RT_SIGACTION | 3329 | #ifndef CONFIG_ODD_RT_SIGACTION |
3238 | /** | 3330 | /** |
3239 | * sys_rt_sigaction - alter an action taken by a process | 3331 | * sys_rt_sigaction - alter an action taken by a process |
3240 | * @sig: signal to be sent | 3332 | * @sig: signal to be sent |
@@ -3268,7 +3360,132 @@ SYSCALL_DEFINE4(rt_sigaction, int, sig, | |||
3268 | out: | 3360 | out: |
3269 | return ret; | 3361 | return ret; |
3270 | } | 3362 | } |
3271 | #endif /* __ARCH_WANT_SYS_RT_SIGACTION */ | 3363 | #ifdef CONFIG_COMPAT |
3364 | COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig, | ||
3365 | const struct compat_sigaction __user *, act, | ||
3366 | struct compat_sigaction __user *, oact, | ||
3367 | compat_size_t, sigsetsize) | ||
3368 | { | ||
3369 | struct k_sigaction new_ka, old_ka; | ||
3370 | compat_sigset_t mask; | ||
3371 | #ifdef __ARCH_HAS_SA_RESTORER | ||
3372 | compat_uptr_t restorer; | ||
3373 | #endif | ||
3374 | int ret; | ||
3375 | |||
3376 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
3377 | if (sigsetsize != sizeof(compat_sigset_t)) | ||
3378 | return -EINVAL; | ||
3379 | |||
3380 | if (act) { | ||
3381 | compat_uptr_t handler; | ||
3382 | ret = get_user(handler, &act->sa_handler); | ||
3383 | new_ka.sa.sa_handler = compat_ptr(handler); | ||
3384 | #ifdef __ARCH_HAS_SA_RESTORER | ||
3385 | ret |= get_user(restorer, &act->sa_restorer); | ||
3386 | new_ka.sa.sa_restorer = compat_ptr(restorer); | ||
3387 | #endif | ||
3388 | ret |= copy_from_user(&mask, &act->sa_mask, sizeof(mask)); | ||
3389 | ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
3390 | if (ret) | ||
3391 | return -EFAULT; | ||
3392 | sigset_from_compat(&new_ka.sa.sa_mask, &mask); | ||
3393 | } | ||
3394 | |||
3395 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
3396 | if (!ret && oact) { | ||
3397 | sigset_to_compat(&mask, &old_ka.sa.sa_mask); | ||
3398 | ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), | ||
3399 | &oact->sa_handler); | ||
3400 | ret |= copy_to_user(&oact->sa_mask, &mask, sizeof(mask)); | ||
3401 | ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
3402 | #ifdef __ARCH_HAS_SA_RESTORER | ||
3403 | ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), | ||
3404 | &oact->sa_restorer); | ||
3405 | #endif | ||
3406 | } | ||
3407 | return ret; | ||
3408 | } | ||
3409 | #endif | ||
3410 | #endif /* !CONFIG_ODD_RT_SIGACTION */ | ||
3411 | |||
3412 | #ifdef CONFIG_OLD_SIGACTION | ||
3413 | SYSCALL_DEFINE3(sigaction, int, sig, | ||
3414 | const struct old_sigaction __user *, act, | ||
3415 | struct old_sigaction __user *, oact) | ||
3416 | { | ||
3417 | struct k_sigaction new_ka, old_ka; | ||
3418 | int ret; | ||
3419 | |||
3420 | if (act) { | ||
3421 | old_sigset_t mask; | ||
3422 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
3423 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | ||
3424 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || | ||
3425 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
3426 | __get_user(mask, &act->sa_mask)) | ||
3427 | return -EFAULT; | ||
3428 | #ifdef __ARCH_HAS_KA_RESTORER | ||
3429 | new_ka.ka_restorer = NULL; | ||
3430 | #endif | ||
3431 | siginitset(&new_ka.sa.sa_mask, mask); | ||
3432 | } | ||
3433 | |||
3434 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
3435 | |||
3436 | if (!ret && oact) { | ||
3437 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
3438 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | ||
3439 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || | ||
3440 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
3441 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
3442 | return -EFAULT; | ||
3443 | } | ||
3444 | |||
3445 | return ret; | ||
3446 | } | ||
3447 | #endif | ||
3448 | #ifdef CONFIG_COMPAT_OLD_SIGACTION | ||
3449 | COMPAT_SYSCALL_DEFINE3(sigaction, int, sig, | ||
3450 | const struct compat_old_sigaction __user *, act, | ||
3451 | struct compat_old_sigaction __user *, oact) | ||
3452 | { | ||
3453 | struct k_sigaction new_ka, old_ka; | ||
3454 | int ret; | ||
3455 | compat_old_sigset_t mask; | ||
3456 | compat_uptr_t handler, restorer; | ||
3457 | |||
3458 | if (act) { | ||
3459 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
3460 | __get_user(handler, &act->sa_handler) || | ||
3461 | __get_user(restorer, &act->sa_restorer) || | ||
3462 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
3463 | __get_user(mask, &act->sa_mask)) | ||
3464 | return -EFAULT; | ||
3465 | |||
3466 | #ifdef __ARCH_HAS_KA_RESTORER | ||
3467 | new_ka.ka_restorer = NULL; | ||
3468 | #endif | ||
3469 | new_ka.sa.sa_handler = compat_ptr(handler); | ||
3470 | new_ka.sa.sa_restorer = compat_ptr(restorer); | ||
3471 | siginitset(&new_ka.sa.sa_mask, mask); | ||
3472 | } | ||
3473 | |||
3474 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
3475 | |||
3476 | if (!ret && oact) { | ||
3477 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
3478 | __put_user(ptr_to_compat(old_ka.sa.sa_handler), | ||
3479 | &oact->sa_handler) || | ||
3480 | __put_user(ptr_to_compat(old_ka.sa.sa_restorer), | ||
3481 | &oact->sa_restorer) || | ||
3482 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
3483 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
3484 | return -EFAULT; | ||
3485 | } | ||
3486 | return ret; | ||
3487 | } | ||
3488 | #endif | ||
3272 | 3489 | ||
3273 | #ifdef __ARCH_WANT_SYS_SGETMASK | 3490 | #ifdef __ARCH_WANT_SYS_SGETMASK |
3274 | 3491 | ||
@@ -3336,7 +3553,6 @@ int sigsuspend(sigset_t *set) | |||
3336 | return -ERESTARTNOHAND; | 3553 | return -ERESTARTNOHAND; |
3337 | } | 3554 | } |
3338 | 3555 | ||
3339 | #ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND | ||
3340 | /** | 3556 | /** |
3341 | * sys_rt_sigsuspend - replace the signal mask for a value with the | 3557 | * sys_rt_sigsuspend - replace the signal mask for a value with the |
3342 | * @unewset value until a signal is received | 3558 | * @unewset value until a signal is received |
@@ -3355,7 +3571,45 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize) | |||
3355 | return -EFAULT; | 3571 | return -EFAULT; |
3356 | return sigsuspend(&newset); | 3572 | return sigsuspend(&newset); |
3357 | } | 3573 | } |
3358 | #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */ | 3574 | |
3575 | #ifdef CONFIG_COMPAT | ||
3576 | COMPAT_SYSCALL_DEFINE2(rt_sigsuspend, compat_sigset_t __user *, unewset, compat_size_t, sigsetsize) | ||
3577 | { | ||
3578 | #ifdef __BIG_ENDIAN | ||
3579 | sigset_t newset; | ||
3580 | compat_sigset_t newset32; | ||
3581 | |||
3582 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
3583 | if (sigsetsize != sizeof(sigset_t)) | ||
3584 | return -EINVAL; | ||
3585 | |||
3586 | if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) | ||
3587 | return -EFAULT; | ||
3588 | sigset_from_compat(&newset, &newset32); | ||
3589 | return sigsuspend(&newset); | ||
3590 | #else | ||
3591 | /* on little-endian bitmaps don't care about granularity */ | ||
3592 | return sys_rt_sigsuspend((sigset_t __user *)unewset, sigsetsize); | ||
3593 | #endif | ||
3594 | } | ||
3595 | #endif | ||
3596 | |||
3597 | #ifdef CONFIG_OLD_SIGSUSPEND | ||
3598 | SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) | ||
3599 | { | ||
3600 | sigset_t blocked; | ||
3601 | siginitset(&blocked, mask); | ||
3602 | return sigsuspend(&blocked); | ||
3603 | } | ||
3604 | #endif | ||
3605 | #ifdef CONFIG_OLD_SIGSUSPEND3 | ||
3606 | SYSCALL_DEFINE3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask) | ||
3607 | { | ||
3608 | sigset_t blocked; | ||
3609 | siginitset(&blocked, mask); | ||
3610 | return sigsuspend(&blocked); | ||
3611 | } | ||
3612 | #endif | ||
3359 | 3613 | ||
3360 | __attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma) | 3614 | __attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma) |
3361 | { | 3615 | { |