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 | /* |
