diff options
| author | Takashi Iwai <tiwai@suse.de> | 2012-05-21 12:45:18 +0200 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2012-05-21 12:45:18 +0200 | 
| commit | 775b2449bdba7c97dda9f274c92bf7a83dac4142 (patch) | |
| tree | b4bee45c13762ea93642b1e38c62de454e51cf5d /kernel/compat.c | |
| parent | 21363cf0ca5c9c62e34e37422fb1d13d70d3de3c (diff) | |
| parent | 5fb86e5d4a951ddb0474cdfd809380c8e2a8d101 (diff) | |
| download | olio-linux-3.10-775b2449bdba7c97dda9f274c92bf7a83dac4142.tar.xz olio-linux-3.10-775b2449bdba7c97dda9f274c92bf7a83dac4142.zip  | |
Merge branch 'topic/asoc' into for-linus
Diffstat (limited to 'kernel/compat.c')
| -rw-r--r-- | kernel/compat.c | 63 | 
1 files changed, 46 insertions, 17 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 74ff8498809..d2c67aa49ae 100644 --- a/kernel/compat.c +++ b/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  |