From d96e86c7415ead4d5330715cc4afa3989e4861e0 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 10 May 2012 10:04:36 -0300 Subject: [PATCH] --- yaml --- r: 300131 b: refs/heads/master c: b7dafa0ef3145c31d7753be0a08b3cbda51f0209 h: refs/heads/master i: 300129: 216dad50b0cb7a590016cc42460eca01d119cd29 300127: 92bd6e5c1201cd25f59c3f66c4f890cd5f8a832e v: v3 --- [refs] | 2 +- trunk/kernel/compat.c | 63 +++++++++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/[refs] b/[refs] index 7ff8fcda2e4d..b09d177c5f5e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7ee94d97aafacf5a019b3578e0eae6daa2e2bcd5 +refs/heads/master: b7dafa0ef3145c31d7753be0a08b3cbda51f0209 diff --git a/trunk/kernel/compat.c b/trunk/kernel/compat.c index 74ff8498809a..d2c67aa49ae6 100644 --- a/trunk/kernel/compat.c +++ b/trunk/kernel/compat.c @@ -372,25 +372,54 @@ asmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set) #ifdef __ARCH_WANT_SYS_SIGPROCMASK -asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, - compat_old_sigset_t __user *oset) +/* + * sys_sigprocmask SIG_SETMASK sets the first (compat) word of the + * blocked set of signals to the supplied signal set + */ +static inline void compat_sig_setmask(sigset_t *blocked, compat_sigset_word set) { - old_sigset_t s; - long ret; - mm_segment_t old_fs; + memcpy(blocked->sig, &set, sizeof(set)); +} - if (set && get_user(s, set)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_sigprocmask(how, - set ? (old_sigset_t __user *) &s : NULL, - oset ? (old_sigset_t __user *) &s : NULL); - set_fs(old_fs); - if (ret == 0) - if (oset) - ret = put_user(s, oset); - return ret; +asmlinkage long compat_sys_sigprocmask(int how, + compat_old_sigset_t __user *nset, + compat_old_sigset_t __user *oset) +{ + old_sigset_t old_set, new_set; + sigset_t new_blocked; + + old_set = current->blocked.sig[0]; + + if (nset) { + if (get_user(new_set, nset)) + return -EFAULT; + new_set &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP)); + + new_blocked = current->blocked; + + switch (how) { + case SIG_BLOCK: + sigaddsetmask(&new_blocked, new_set); + break; + case SIG_UNBLOCK: + sigdelsetmask(&new_blocked, new_set); + break; + case SIG_SETMASK: + compat_sig_setmask(&new_blocked, new_set); + break; + default: + return -EINVAL; + } + + set_current_blocked(&new_blocked); + } + + if (oset) { + if (put_user(old_set, oset)) + return -EFAULT; + } + + return 0; } #endif