Commit 322a56cb1fcbe228eee5cdb8a9c6df9f797d998c
1 parent
ad4b65a434
Exists in
master
and in
20 other branches
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>
Showing 4 changed files with 63 additions and 2 deletions Side-by-side Diff
arch/Kconfig
include/linux/compat.h
... | ... | @@ -401,7 +401,8 @@ |
401 | 401 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); |
402 | 402 | |
403 | 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 | 407 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, |
407 | 408 | compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, |
... | ... | @@ -592,6 +593,11 @@ |
592 | 593 | struct compat_timespec __user *uts, compat_size_t sigsetsize); |
593 | 594 | asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, |
594 | 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 | 601 | asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); |
596 | 602 | asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, |
597 | 603 | unsigned long arg); |
kernel/compat.c
... | ... | @@ -971,7 +971,7 @@ |
971 | 971 | } |
972 | 972 | |
973 | 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 | 976 | switch (_NSIG_WORDS) { |
977 | 977 | case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 ); |
... | ... | @@ -981,6 +981,17 @@ |
981 | 981 | } |
982 | 982 | } |
983 | 983 | EXPORT_SYMBOL_GPL(sigset_from_compat); |
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 | +} | |
984 | 995 | |
985 | 996 | asmlinkage long |
986 | 997 | compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, |
kernel/signal.c
... | ... | @@ -2613,6 +2613,47 @@ |
2613 | 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 | 2657 | long do_sigpending(void __user *set, unsigned long sigsetsize) |
2617 | 2658 | { |
2618 | 2659 | long error = -EINVAL; |