diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-12-25 19:09:45 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-03 15:09:23 -0500 |
commit | 495dfbf767553980dbd40a19a96a8ca5fa1be616 (patch) | |
tree | 5c6d499f130f17abad2ee9407272d92e9192879a | |
parent | 08d32fe504a7670cab3190c624448695adcf70e4 (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/Kconfig | 11 | ||||
-rw-r--r-- | include/linux/compat.h | 14 | ||||
-rw-r--r-- | include/linux/signal.h | 9 | ||||
-rw-r--r-- | include/linux/syscalls.h | 5 | ||||
-rw-r--r-- | kernel/signal.c | 78 |
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 | ||
403 | config 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 | |||
411 | config COMPAT_OLD_SIGACTION | ||
412 | bool | ||
413 | |||
403 | source "kernel/gcov/Kconfig" | 414 | source "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 | ||
303 | struct 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 | |||
302 | struct compat_statfs; | 311 | struct compat_statfs; |
303 | struct compat_statfs64; | 312 | struct compat_statfs64; |
304 | struct compat_old_linux_dirent; | 313 | struct 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); |
384 | long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig, | 393 | long 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 | ||
396 | asmlinkage 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 | ||
387 | static inline int compat_timeval_compare(struct compat_timeval *lhs, | 401 | static 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 | ||
274 | struct 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 | ||
273 | extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); | 282 | extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); |
274 | extern void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping); | 283 | extern 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); | |||
385 | asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask); | 385 | asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask); |
386 | #endif | 386 | #endif |
387 | 387 | ||
388 | #ifdef CONFIG_OLD_SIGACTION | ||
389 | asmlinkage 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 |
389 | asmlinkage long sys_rt_sigaction(int, | 394 | asmlinkage 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 | ||
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 | ||
3489 | |||
3412 | #ifdef __ARCH_WANT_SYS_SGETMASK | 3490 | #ifdef __ARCH_WANT_SYS_SGETMASK |
3413 | 3491 | ||
3414 | /* | 3492 | /* |