Commit 322a56cb1fcbe228eee5cdb8a9c6df9f797d998c

Authored by Al Viro
1 parent ad4b65a434

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

... ... @@ -359,6 +359,9 @@
359 359 config GENERIC_SIGALTSTACK
360 360 bool
361 361  
  362 +config GENERIC_COMPAT_RT_SIGPROCMASK
  363 + bool
  364 +
362 365 #
363 366 # ABI hall of shame
364 367 #
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);
... ... @@ -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,
... ... @@ -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;