diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-12-25 14:31:38 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-03 15:09:19 -0500 |
commit | fe9c1db2cfc363cd30ecfe6480481b280abf8c0a (patch) | |
tree | 0382530cd58c72b56b9860d7bc5bab65a356d9a9 /kernel/signal.c | |
parent | 322a56cb1fcbe228eee5cdb8a9c6df9f797d998c (diff) |
generic compat_sys_rt_sigpending()
conditional on GENERIC_COMPAT_RT_SIGPENDING; by the end of that series
it will become the same thing as COMPAT and conditional will die out.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index bce1222b7315..3040c349b0e1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -2654,28 +2654,19 @@ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, | |||
2654 | #endif | 2654 | #endif |
2655 | #endif | 2655 | #endif |
2656 | 2656 | ||
2657 | long do_sigpending(void __user *set, unsigned long sigsetsize) | 2657 | static int do_sigpending(void *set, unsigned long sigsetsize) |
2658 | { | 2658 | { |
2659 | long error = -EINVAL; | ||
2660 | sigset_t pending; | ||
2661 | |||
2662 | if (sigsetsize > sizeof(sigset_t)) | 2659 | if (sigsetsize > sizeof(sigset_t)) |
2663 | goto out; | 2660 | return -EINVAL; |
2664 | 2661 | ||
2665 | spin_lock_irq(¤t->sighand->siglock); | 2662 | spin_lock_irq(¤t->sighand->siglock); |
2666 | sigorsets(&pending, ¤t->pending.signal, | 2663 | sigorsets(set, ¤t->pending.signal, |
2667 | ¤t->signal->shared_pending.signal); | 2664 | ¤t->signal->shared_pending.signal); |
2668 | spin_unlock_irq(¤t->sighand->siglock); | 2665 | spin_unlock_irq(¤t->sighand->siglock); |
2669 | 2666 | ||
2670 | /* Outside the lock because only this thread touches it. */ | 2667 | /* Outside the lock because only this thread touches it. */ |
2671 | sigandsets(&pending, ¤t->blocked, &pending); | 2668 | sigandsets(set, ¤t->blocked, set); |
2672 | 2669 | return 0; | |
2673 | error = -EFAULT; | ||
2674 | if (!copy_to_user(set, &pending, sigsetsize)) | ||
2675 | error = 0; | ||
2676 | |||
2677 | out: | ||
2678 | return error; | ||
2679 | } | 2670 | } |
2680 | 2671 | ||
2681 | /** | 2672 | /** |
@@ -2684,10 +2675,37 @@ out: | |||
2684 | * @set: stores pending signals | 2675 | * @set: stores pending signals |
2685 | * @sigsetsize: size of sigset_t type or larger | 2676 | * @sigsetsize: size of sigset_t type or larger |
2686 | */ | 2677 | */ |
2687 | SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, set, size_t, sigsetsize) | 2678 | SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize) |
2679 | { | ||
2680 | sigset_t set; | ||
2681 | int err = do_sigpending(&set, sigsetsize); | ||
2682 | if (!err && copy_to_user(uset, &set, sigsetsize)) | ||
2683 | err = -EFAULT; | ||
2684 | return err; | ||
2685 | } | ||
2686 | |||
2687 | #ifdef CONFIG_COMPAT | ||
2688 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGPENDING | ||
2689 | COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, | ||
2690 | compat_size_t, sigsetsize) | ||
2688 | { | 2691 | { |
2689 | return do_sigpending(set, sigsetsize); | 2692 | #ifdef __BIG_ENDIAN |
2693 | sigset_t set; | ||
2694 | int err = do_sigpending(&set, sigsetsize); | ||
2695 | if (!err) { | ||
2696 | compat_sigset_t set32; | ||
2697 | sigset_to_compat(&set32, &set); | ||
2698 | /* we can get here only if sigsetsize <= sizeof(set) */ | ||
2699 | if (copy_to_user(uset, &set32, sigsetsize)) | ||
2700 | err = -EFAULT; | ||
2701 | } | ||
2702 | return err; | ||
2703 | #else | ||
2704 | return sys_rt_sigpending((sigset_t __user *)uset, sigsetsize); | ||
2705 | #endif | ||
2690 | } | 2706 | } |
2707 | #endif | ||
2708 | #endif | ||
2691 | 2709 | ||
2692 | #ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER | 2710 | #ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER |
2693 | 2711 | ||
@@ -3216,7 +3234,7 @@ int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp) | |||
3216 | */ | 3234 | */ |
3217 | SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set) | 3235 | SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set) |
3218 | { | 3236 | { |
3219 | return do_sigpending(set, sizeof(*set)); | 3237 | return sys_rt_sigpending((sigset_t __user *)set, sizeof(old_sigset_t)); |
3220 | } | 3238 | } |
3221 | 3239 | ||
3222 | #endif | 3240 | #endif |