diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-12-25 18:38:15 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-03 15:09:23 -0500 |
commit | 08d32fe504a7670cab3190c624448695adcf70e4 (patch) | |
tree | a6fcff4e53049064fe4d9e060e2bb41ae842fb42 | |
parent | 574c4866e33d648520a8bd5bf6f573ea6e554e88 (diff) |
generic sys_compat_rt_sigaction()
Again, protected by a temporary config symbol (GENERIC_COMPAT_RT_SIGACTION);
will be gone by the end of series.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | arch/Kconfig | 3 | ||||
-rw-r--r-- | include/linux/compat.h | 24 | ||||
-rw-r--r-- | kernel/signal.c | 49 |
3 files changed, 76 insertions, 0 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 6b1df95ffefc..3b4a416fc448 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -368,6 +368,9 @@ config GENERIC_COMPAT_RT_SIGPENDING | |||
368 | config GENERIC_COMPAT_RT_SIGQUEUEINFO | 368 | config GENERIC_COMPAT_RT_SIGQUEUEINFO |
369 | bool | 369 | bool |
370 | 370 | ||
371 | config GENERIC_COMPAT_RT_SIGACTION | ||
372 | bool | ||
373 | |||
371 | # | 374 | # |
372 | # ABI hall of shame | 375 | # ABI hall of shame |
373 | # | 376 | # |
diff --git a/include/linux/compat.h b/include/linux/compat.h index bbee15ef3ae9..0d53ab4f79c5 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
@@ -142,6 +142,22 @@ typedef struct { | |||
142 | compat_sigset_word sig[_COMPAT_NSIG_WORDS]; | 142 | compat_sigset_word sig[_COMPAT_NSIG_WORDS]; |
143 | } compat_sigset_t; | 143 | } compat_sigset_t; |
144 | 144 | ||
145 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGACTION | ||
146 | struct compat_sigaction { | ||
147 | #ifndef __ARCH_HAS_ODD_SIGACTION | ||
148 | compat_uptr_t sa_handler; | ||
149 | compat_ulong_t sa_flags; | ||
150 | #else | ||
151 | compat_ulong_t sa_flags; | ||
152 | compat_uptr_t sa_handler; | ||
153 | #endif | ||
154 | #ifdef __ARCH_HAS_SA_RESTORER | ||
155 | compat_uptr_t sa_restorer; | ||
156 | #endif | ||
157 | compat_sigset_t sa_mask __packed; | ||
158 | }; | ||
159 | #endif | ||
160 | |||
145 | /* | 161 | /* |
146 | * These functions operate strictly on struct compat_time* | 162 | * These functions operate strictly on struct compat_time* |
147 | */ | 163 | */ |
@@ -602,6 +618,14 @@ asmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, | |||
602 | asmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset, | 618 | asmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset, |
603 | compat_size_t sigsetsize); | 619 | compat_size_t sigsetsize); |
604 | #endif | 620 | #endif |
621 | #ifndef CONFIG_ODD_RT_SIGACTION | ||
622 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGACTION | ||
623 | asmlinkage long compat_sys_rt_sigaction(int, | ||
624 | const struct compat_sigaction __user *, | ||
625 | struct compat_sigaction __user *, | ||
626 | compat_size_t); | ||
627 | #endif | ||
628 | #endif | ||
605 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGQUEUEINFO | 629 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGQUEUEINFO |
606 | asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig, | 630 | asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig, |
607 | struct compat_siginfo __user *uinfo); | 631 | struct compat_siginfo __user *uinfo); |
diff --git a/kernel/signal.c b/kernel/signal.c index 5a4aed1244fb..f3665f3de660 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -3358,6 +3358,55 @@ SYSCALL_DEFINE4(rt_sigaction, int, sig, | |||
3358 | out: | 3358 | out: |
3359 | return ret; | 3359 | return ret; |
3360 | } | 3360 | } |
3361 | #ifdef CONFIG_COMPAT | ||
3362 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGACTION | ||
3363 | COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig, | ||
3364 | const struct compat_sigaction __user *, act, | ||
3365 | struct compat_sigaction __user *, oact, | ||
3366 | compat_size_t, sigsetsize) | ||
3367 | { | ||
3368 | struct k_sigaction new_ka, old_ka; | ||
3369 | compat_sigset_t mask; | ||
3370 | #ifdef __ARCH_HAS_SA_RESTORER | ||
3371 | compat_uptr_t restorer; | ||
3372 | #endif | ||
3373 | int ret; | ||
3374 | |||
3375 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
3376 | if (sigsetsize != sizeof(compat_sigset_t)) | ||
3377 | return -EINVAL; | ||
3378 | |||
3379 | if (act) { | ||
3380 | compat_uptr_t handler; | ||
3381 | ret = get_user(handler, &act->sa_handler); | ||
3382 | new_ka.sa.sa_handler = compat_ptr(handler); | ||
3383 | #ifdef __ARCH_HAS_SA_RESTORER | ||
3384 | ret |= get_user(restorer, &act->sa_restorer); | ||
3385 | new_ka.sa.sa_restorer = compat_ptr(restorer); | ||
3386 | #endif | ||
3387 | ret |= copy_from_user(&mask, &act->sa_mask, sizeof(mask)); | ||
3388 | ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
3389 | if (ret) | ||
3390 | return -EFAULT; | ||
3391 | sigset_from_compat(&new_ka.sa.sa_mask, &mask); | ||
3392 | } | ||
3393 | |||
3394 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
3395 | if (!ret && oact) { | ||
3396 | sigset_to_compat(&mask, &old_ka.sa.sa_mask); | ||
3397 | ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), | ||
3398 | &oact->sa_handler); | ||
3399 | ret |= copy_to_user(&oact->sa_mask, &mask, sizeof(mask)); | ||
3400 | ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
3401 | #ifdef __ARCH_HAS_SA_RESTORER | ||
3402 | ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), | ||
3403 | &oact->sa_restorer); | ||
3404 | #endif | ||
3405 | } | ||
3406 | return ret; | ||
3407 | } | ||
3408 | #endif | ||
3409 | #endif | ||
3361 | #endif /* !CONFIG_ODD_RT_SIGACTION */ | 3410 | #endif /* !CONFIG_ODD_RT_SIGACTION */ |
3362 | 3411 | ||
3363 | #ifdef __ARCH_WANT_SYS_SGETMASK | 3412 | #ifdef __ARCH_WANT_SYS_SGETMASK |