aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-12-25 19:09:45 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2013-02-03 15:09:23 -0500
commit495dfbf767553980dbd40a19a96a8ca5fa1be616 (patch)
tree5c6d499f130f17abad2ee9407272d92e9192879a
parent08d32fe504a7670cab3190c624448695adcf70e4 (diff)
generic sys_sigaction() and compat_sys_sigaction()
conditional on OLD_SIGACTION/COMPAT_OLD_SIGACTION Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/Kconfig11
-rw-r--r--include/linux/compat.h14
-rw-r--r--include/linux/signal.h9
-rw-r--r--include/linux/syscalls.h5
-rw-r--r--kernel/signal.c78
5 files changed, 117 insertions, 0 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index 3b4a416fc448..e50d3af294d4 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -400,4 +400,15 @@ config OLD_SIGSUSPEND3
400 help 400 help
401 Even weirder antique ABI - three-argument sigsuspend(2) 401 Even weirder antique ABI - three-argument sigsuspend(2)
402 402
403config OLD_SIGACTION
404 bool
405 help
406 Architecture has old sigaction(2) syscall. Nope, not the same
407 as OLD_SIGSUSPEND | OLD_SIGSUSPEND3 - alpha has sigsuspend(2),
408 but fairly different variant of sigaction(2), thanks to OSF/1
409 compatibility...
410
411config COMPAT_OLD_SIGACTION
412 bool
413
403source "kernel/gcov/Kconfig" 414source "kernel/gcov/Kconfig"
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 0d53ab4f79c5..e20b8b404ae9 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -299,6 +299,15 @@ struct compat_robust_list_head {
299 compat_uptr_t list_op_pending; 299 compat_uptr_t list_op_pending;
300}; 300};
301 301
302#ifdef CONFIG_COMPAT_OLD_SIGACTION
303struct compat_old_sigaction {
304 compat_uptr_t sa_handler;
305 compat_old_sigset_t sa_mask;
306 compat_ulong_t sa_flags;
307 compat_uptr_t sa_restorer;
308};
309#endif
310
302struct compat_statfs; 311struct compat_statfs;
303struct compat_statfs64; 312struct compat_statfs64;
304struct compat_old_linux_dirent; 313struct compat_old_linux_dirent;
@@ -383,6 +392,11 @@ int get_compat_sigevent(struct sigevent *event,
383 const struct compat_sigevent __user *u_event); 392 const struct compat_sigevent __user *u_event);
384long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig, 393long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig,
385 struct compat_siginfo __user *uinfo); 394 struct compat_siginfo __user *uinfo);
395#ifdef CONFIG_COMPAT_OLD_SIGACTION
396asmlinkage long compat_sys_sigaction(int sig,
397 const struct compat_old_sigaction __user *act,
398 struct compat_old_sigaction __user *oact);
399#endif
386 400
387static inline int compat_timeval_compare(struct compat_timeval *lhs, 401static inline int compat_timeval_compare(struct compat_timeval *lhs,
388 struct compat_timeval *rhs) 402 struct compat_timeval *rhs)
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 0b6878e882da..e28e8d455d6e 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -269,6 +269,15 @@ struct k_sigaction {
269 __sigrestore_t ka_restorer; 269 __sigrestore_t ka_restorer;
270#endif 270#endif
271}; 271};
272
273#ifdef CONFIG_OLD_SIGACTION
274struct old_sigaction {
275 __sighandler_t sa_handler;
276 old_sigset_t sa_mask;
277 unsigned long sa_flags;
278 __sigrestore_t sa_restorer;
279};
280#endif
272 281
273extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); 282extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
274extern void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping); 283extern void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 1c4938bf901e..02b045012785 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -385,6 +385,11 @@ asmlinkage long sys_sigsuspend(old_sigset_t mask);
385asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask); 385asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask);
386#endif 386#endif
387 387
388#ifdef CONFIG_OLD_SIGACTION
389asmlinkage long sys_sigaction(int, const struct old_sigaction __user *,
390 struct old_sigaction __user *);
391#endif
392
388#ifndef CONFIG_ODD_RT_SIGACTION 393#ifndef CONFIG_ODD_RT_SIGACTION
389asmlinkage long sys_rt_sigaction(int, 394asmlinkage long sys_rt_sigaction(int,
390 const struct sigaction __user *, 395 const struct sigaction __user *,
diff --git a/kernel/signal.c b/kernel/signal.c
index f3665f3de660..79998f5b0f11 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3409,6 +3409,84 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig,
3409#endif 3409#endif
3410#endif /* !CONFIG_ODD_RT_SIGACTION */ 3410#endif /* !CONFIG_ODD_RT_SIGACTION */
3411 3411
3412#ifdef CONFIG_OLD_SIGACTION
3413SYSCALL_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
3449COMPAT_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
3489
3412#ifdef __ARCH_WANT_SYS_SGETMASK 3490#ifdef __ARCH_WANT_SYS_SGETMASK
3413 3491
3414/* 3492/*