diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-12-25 13:32:58 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-03 15:09:19 -0500 |
| commit | 322a56cb1fcbe228eee5cdb8a9c6df9f797d998c (patch) | |
| tree | feedbad82fdfacf9f4d5ddd343905f6057a71fee | |
| parent | ad4b65a434bdd2ff37d095ab1ccd836203e985ba (diff) | |
generic compat_sys_rt_sigprocmask()
conditional on GENERIC_COMPAT_RT_SIGPROCMASK; by the end of that series
it will become the same thing as COMPAT and conditional will die out.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | arch/Kconfig | 3 | ||||
| -rw-r--r-- | include/linux/compat.h | 8 | ||||
| -rw-r--r-- | kernel/compat.c | 13 | ||||
| -rw-r--r-- | kernel/signal.c | 41 |
4 files changed, 63 insertions, 2 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 6e4c32a5a358..374a68adbf1f 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
| @@ -359,6 +359,9 @@ config MODULES_USE_ELF_REL | |||
| 359 | config GENERIC_SIGALTSTACK | 359 | config GENERIC_SIGALTSTACK |
| 360 | bool | 360 | bool |
| 361 | 361 | ||
| 362 | config GENERIC_COMPAT_RT_SIGPROCMASK | ||
| 363 | bool | ||
| 364 | |||
| 362 | # | 365 | # |
| 363 | # ABI hall of shame | 366 | # ABI hall of shame |
| 364 | # | 367 | # |
diff --git a/include/linux/compat.h b/include/linux/compat.h index dec7e2d18875..9d3c2a98d537 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
| @@ -401,7 +401,8 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, | |||
| 401 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); | 401 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); |
| 402 | 402 | ||
| 403 | extern int compat_printk(const char *fmt, ...); | 403 | extern int compat_printk(const char *fmt, ...); |
| 404 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); | 404 | extern void sigset_from_compat(sigset_t *set, const compat_sigset_t *compat); |
| 405 | extern void sigset_to_compat(compat_sigset_t *compat, const sigset_t *set); | ||
| 405 | 406 | ||
| 406 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, | 407 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, |
| 407 | compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, | 408 | compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, |
| @@ -592,6 +593,11 @@ asmlinkage long compat_sys_rt_sigtimedwait(compat_sigset_t __user *uthese, | |||
| 592 | struct compat_timespec __user *uts, compat_size_t sigsetsize); | 593 | struct compat_timespec __user *uts, compat_size_t sigsetsize); |
| 593 | asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, | 594 | asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, |
| 594 | compat_size_t sigsetsize); | 595 | compat_size_t sigsetsize); |
| 596 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGPROCMASK | ||
| 597 | asmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, | ||
| 598 | compat_sigset_t __user *oset, | ||
| 599 | compat_size_t sigsetsize); | ||
| 600 | #endif | ||
| 595 | asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); | 601 | asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); |
| 596 | asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, | 602 | asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, |
| 597 | unsigned long arg); | 603 | unsigned long arg); |
diff --git a/kernel/compat.c b/kernel/compat.c index 0c07d435254f..e2a9c4785988 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
| @@ -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,6 +982,17 @@ 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 | void | ||
| 986 | sigset_to_compat(compat_sigset_t *compat, const sigset_t *set) | ||
| 987 | { | ||
| 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 | |||
| 985 | asmlinkage long | 996 | asmlinkage long |
| 986 | compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | 997 | compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, |
| 987 | struct compat_siginfo __user *uinfo, | 998 | struct compat_siginfo __user *uinfo, |
diff --git a/kernel/signal.c b/kernel/signal.c index 4a0934e03d5c..bce1222b7315 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -2613,6 +2613,47 @@ SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, nset, | |||
| 2613 | return 0; | 2613 | return 0; |
| 2614 | } | 2614 | } |
| 2615 | 2615 | ||
| 2616 | #ifdef CONFIG_COMPAT | ||
| 2617 | #ifdef CONFIG_GENERIC_COMPAT_RT_SIGPROCMASK | ||
| 2618 | COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, | ||
| 2619 | compat_sigset_t __user *, oset, compat_size_t, sigsetsize) | ||
| 2620 | { | ||
| 2621 | #ifdef __BIG_ENDIAN | ||
| 2622 | sigset_t old_set = current->blocked; | ||
| 2623 | |||
| 2624 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
| 2625 | if (sigsetsize != sizeof(sigset_t)) | ||
| 2626 | return -EINVAL; | ||
| 2627 | |||
| 2628 | if (nset) { | ||
| 2629 | compat_sigset_t new32; | ||
| 2630 | sigset_t new_set; | ||
| 2631 | int error; | ||
| 2632 | if (copy_from_user(&new32, nset, sizeof(compat_sigset_t))) | ||
| 2633 | return -EFAULT; | ||
| 2634 | |||
| 2635 | sigset_from_compat(&new_set, &new32); | ||
| 2636 | sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); | ||
| 2637 | |||
| 2638 | error = sigprocmask(how, &new_set, NULL); | ||
| 2639 | if (error) | ||
| 2640 | return error; | ||
| 2641 | } | ||
| 2642 | if (oset) { | ||
| 2643 | compat_sigset_t old32; | ||
| 2644 | sigset_to_compat(&old32, &old_set); | ||
| 2645 | if (copy_to_user(oset, &old_set, sizeof(sigset_t))) | ||
| 2646 | return -EFAULT; | ||
| 2647 | } | ||
| 2648 | return 0; | ||
| 2649 | #else | ||
| 2650 | return sys_rt_sigprocmask(how, (sigset_t __user *)nset, | ||
| 2651 | (sigset_t __user *)oset, sigsetsize); | ||
| 2652 | #endif | ||
| 2653 | } | ||
| 2654 | #endif | ||
| 2655 | #endif | ||
| 2656 | |||
| 2616 | long do_sigpending(void __user *set, unsigned long sigsetsize) | 2657 | long do_sigpending(void __user *set, unsigned long sigsetsize) |
| 2617 | { | 2658 | { |
| 2618 | long error = -EINVAL; | 2659 | long error = -EINVAL; |
