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 | |
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')
-rw-r--r-- | kernel/compat.c | 72 | ||||
-rw-r--r-- | kernel/futex_compat.c | 19 | ||||
-rw-r--r-- | kernel/signal.c | 332 |
3 files changed, 329 insertions, 94 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index f4bddb900186..19971d8c7299 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -290,8 +290,8 @@ static inline long put_compat_itimerval(struct compat_itimerval __user *o, | |||
290 | __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); | 290 | __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); |
291 | } | 291 | } |
292 | 292 | ||
293 | asmlinkage long compat_sys_getitimer(int which, | 293 | COMPAT_SYSCALL_DEFINE2(getitimer, int, which, |
294 | struct compat_itimerval __user *it) | 294 | struct compat_itimerval __user *, it) |
295 | { | 295 | { |
296 | struct itimerval kit; | 296 | struct itimerval kit; |
297 | int error; | 297 | int error; |
@@ -302,9 +302,9 @@ asmlinkage long compat_sys_getitimer(int which, | |||
302 | return error; | 302 | return error; |
303 | } | 303 | } |
304 | 304 | ||
305 | asmlinkage long compat_sys_setitimer(int which, | 305 | COMPAT_SYSCALL_DEFINE3(setitimer, int, which, |
306 | struct compat_itimerval __user *in, | 306 | struct compat_itimerval __user *, in, |
307 | struct compat_itimerval __user *out) | 307 | struct compat_itimerval __user *, out) |
308 | { | 308 | { |
309 | struct itimerval kin, kout; | 309 | struct itimerval kin, kout; |
310 | int error; | 310 | int error; |
@@ -381,9 +381,9 @@ static inline void compat_sig_setmask(sigset_t *blocked, compat_sigset_word set) | |||
381 | memcpy(blocked->sig, &set, sizeof(set)); | 381 | memcpy(blocked->sig, &set, sizeof(set)); |
382 | } | 382 | } |
383 | 383 | ||
384 | asmlinkage long compat_sys_sigprocmask(int how, | 384 | COMPAT_SYSCALL_DEFINE3(sigprocmask, int, how, |
385 | compat_old_sigset_t __user *nset, | 385 | compat_old_sigset_t __user *, nset, |
386 | compat_old_sigset_t __user *oset) | 386 | compat_old_sigset_t __user *, oset) |
387 | { | 387 | { |
388 | old_sigset_t old_set, new_set; | 388 | old_sigset_t old_set, new_set; |
389 | sigset_t new_blocked; | 389 | sigset_t new_blocked; |
@@ -971,7 +971,7 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, | |||
971 | } | 971 | } |
972 | 972 | ||
973 | void | 973 | void |
974 | sigset_from_compat (sigset_t *set, compat_sigset_t *compat) | 974 | sigset_from_compat(sigset_t *set, const compat_sigset_t *compat) |
975 | { | 975 | { |
976 | switch (_NSIG_WORDS) { | 976 | switch (_NSIG_WORDS) { |
977 | case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 ); | 977 | case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 ); |
@@ -982,10 +982,20 @@ sigset_from_compat (sigset_t *set, compat_sigset_t *compat) | |||
982 | } | 982 | } |
983 | EXPORT_SYMBOL_GPL(sigset_from_compat); | 983 | EXPORT_SYMBOL_GPL(sigset_from_compat); |
984 | 984 | ||
985 | asmlinkage long | 985 | void |
986 | compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | 986 | sigset_to_compat(compat_sigset_t *compat, const sigset_t *set) |
987 | struct compat_siginfo __user *uinfo, | 987 | { |
988 | struct compat_timespec __user *uts, compat_size_t sigsetsize) | 988 | switch (_NSIG_WORDS) { |
989 | case 4: compat->sig[7] = (set->sig[3] >> 32); compat->sig[6] = set->sig[3]; | ||
990 | case 3: compat->sig[5] = (set->sig[2] >> 32); compat->sig[4] = set->sig[2]; | ||
991 | case 2: compat->sig[3] = (set->sig[1] >> 32); compat->sig[2] = set->sig[1]; | ||
992 | case 1: compat->sig[1] = (set->sig[0] >> 32); compat->sig[0] = set->sig[0]; | ||
993 | } | ||
994 | } | ||
995 | |||
996 | COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese, | ||
997 | struct compat_siginfo __user *, uinfo, | ||
998 | struct compat_timespec __user *, uts, compat_size_t, sigsetsize) | ||
989 | { | 999 | { |
990 | compat_sigset_t s32; | 1000 | compat_sigset_t s32; |
991 | sigset_t s; | 1001 | sigset_t s; |
@@ -1013,18 +1023,6 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | |||
1013 | } | 1023 | } |
1014 | 1024 | ||
1015 | return ret; | 1025 | return ret; |
1016 | |||
1017 | } | ||
1018 | |||
1019 | asmlinkage long | ||
1020 | compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig, | ||
1021 | struct compat_siginfo __user *uinfo) | ||
1022 | { | ||
1023 | siginfo_t info; | ||
1024 | |||
1025 | if (copy_siginfo_from_user32(&info, uinfo)) | ||
1026 | return -EFAULT; | ||
1027 | return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); | ||
1028 | } | 1026 | } |
1029 | 1027 | ||
1030 | #ifdef __ARCH_WANT_COMPAT_SYS_TIME | 1028 | #ifdef __ARCH_WANT_COMPAT_SYS_TIME |
@@ -1067,23 +1065,6 @@ asmlinkage long compat_sys_stime(compat_time_t __user *tptr) | |||
1067 | 1065 | ||
1068 | #endif /* __ARCH_WANT_COMPAT_SYS_TIME */ | 1066 | #endif /* __ARCH_WANT_COMPAT_SYS_TIME */ |
1069 | 1067 | ||
1070 | #ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | ||
1071 | asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize) | ||
1072 | { | ||
1073 | sigset_t newset; | ||
1074 | compat_sigset_t newset32; | ||
1075 | |||
1076 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
1077 | if (sigsetsize != sizeof(sigset_t)) | ||
1078 | return -EINVAL; | ||
1079 | |||
1080 | if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) | ||
1081 | return -EFAULT; | ||
1082 | sigset_from_compat(&newset, &newset32); | ||
1083 | return sigsuspend(&newset); | ||
1084 | } | ||
1085 | #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */ | ||
1086 | |||
1087 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) | 1068 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) |
1088 | { | 1069 | { |
1089 | struct timex txc; | 1070 | struct timex txc; |
@@ -1222,9 +1203,9 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) | |||
1222 | return 0; | 1203 | return 0; |
1223 | } | 1204 | } |
1224 | 1205 | ||
1225 | #ifdef __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL | 1206 | COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval, |
1226 | asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, | 1207 | compat_pid_t, pid, |
1227 | struct compat_timespec __user *interval) | 1208 | struct compat_timespec __user *, interval) |
1228 | { | 1209 | { |
1229 | struct timespec t; | 1210 | struct timespec t; |
1230 | int ret; | 1211 | int ret; |
@@ -1237,7 +1218,6 @@ asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, | |||
1237 | return -EFAULT; | 1218 | return -EFAULT; |
1238 | return ret; | 1219 | return ret; |
1239 | } | 1220 | } |
1240 | #endif /* __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL */ | ||
1241 | 1221 | ||
1242 | /* | 1222 | /* |
1243 | * Allocate user-space memory for the duration of a single system call, | 1223 | * Allocate user-space memory for the duration of a single system call, |
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index a9642d528630..f9f44fd4d34d 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/nsproxy.h> | 11 | #include <linux/nsproxy.h> |
12 | #include <linux/futex.h> | 12 | #include <linux/futex.h> |
13 | #include <linux/ptrace.h> | 13 | #include <linux/ptrace.h> |
14 | #include <linux/syscalls.h> | ||
14 | 15 | ||
15 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
16 | 17 | ||
@@ -116,9 +117,9 @@ void compat_exit_robust_list(struct task_struct *curr) | |||
116 | } | 117 | } |
117 | } | 118 | } |
118 | 119 | ||
119 | asmlinkage long | 120 | COMPAT_SYSCALL_DEFINE2(set_robust_list, |
120 | compat_sys_set_robust_list(struct compat_robust_list_head __user *head, | 121 | struct compat_robust_list_head __user *, head, |
121 | compat_size_t len) | 122 | compat_size_t, len) |
122 | { | 123 | { |
123 | if (!futex_cmpxchg_enabled) | 124 | if (!futex_cmpxchg_enabled) |
124 | return -ENOSYS; | 125 | return -ENOSYS; |
@@ -131,9 +132,9 @@ compat_sys_set_robust_list(struct compat_robust_list_head __user *head, | |||
131 | return 0; | 132 | return 0; |
132 | } | 133 | } |
133 | 134 | ||
134 | asmlinkage long | 135 | COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid, |
135 | compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, | 136 | compat_uptr_t __user *, head_ptr, |
136 | compat_size_t __user *len_ptr) | 137 | compat_size_t __user *, len_ptr) |
137 | { | 138 | { |
138 | struct compat_robust_list_head __user *head; | 139 | struct compat_robust_list_head __user *head; |
139 | unsigned long ret; | 140 | unsigned long ret; |
@@ -170,9 +171,9 @@ err_unlock: | |||
170 | return ret; | 171 | return ret; |
171 | } | 172 | } |
172 | 173 | ||
173 | asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, | 174 | COMPAT_SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, |
174 | struct compat_timespec __user *utime, u32 __user *uaddr2, | 175 | struct compat_timespec __user *, utime, u32 __user *, uaddr2, |
175 | u32 val3) | 176 | u32, val3) |
176 | { | 177 | { |
177 | struct timespec ts; | 178 | struct timespec ts; |
178 | ktime_t t, *tp = NULL; | 179 | ktime_t t, *tp = NULL; |
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 | { |