diff options
Diffstat (limited to 'kernel/signal.c')
| -rw-r--r-- | kernel/signal.c | 38 | 
1 files changed, 20 insertions, 18 deletions
| diff --git a/kernel/signal.c b/kernel/signal.c index f67545f9394c..d09692b40376 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -423,7 +423,7 @@ still_pending:  		 */  		info->si_signo = sig;  		info->si_errno = 0; -		info->si_code = 0; +		info->si_code = SI_USER;  		info->si_pid = 0;  		info->si_uid = 0;  	} @@ -607,6 +607,17 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s)  	return 1;  } +static inline int is_si_special(const struct siginfo *info) +{ +	return info <= SEND_SIG_FORCED; +} + +static inline bool si_fromuser(const struct siginfo *info) +{ +	return info == SEND_SIG_NOINFO || +		(!is_si_special(info) && SI_FROMUSER(info)); +} +  /*   * Bad permissions for sending the signal   * - the caller must hold at least the RCU read lock @@ -621,7 +632,7 @@ static int check_kill_permission(int sig, struct siginfo *info,  	if (!valid_signal(sig))  		return -EINVAL; -	if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))) +	if (!si_fromuser(info))  		return 0;  	error = audit_signal_info(sig, t); /* Let audit system see the signal */ @@ -949,9 +960,8 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,  	int from_ancestor_ns = 0;  #ifdef CONFIG_PID_NS -	if (!is_si_special(info) && SI_FROMUSER(info) && -			task_pid_nr_ns(current, task_active_pid_ns(t)) <= 0) -		from_ancestor_ns = 1; +	from_ancestor_ns = si_fromuser(info) && +			   !task_pid_nr_ns(current, task_active_pid_ns(t));  #endif  	return __send_signal(sig, info, t, group, from_ancestor_ns); @@ -1052,12 +1062,6 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)  	return ret;  } -void -force_sig_specific(int sig, struct task_struct *t) -{ -	force_sig_info(sig, SEND_SIG_FORCED, t); -} -  /*   * Nuke all other threads in the group.   */ @@ -1187,8 +1191,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,  		goto out_unlock;  	}  	pcred = __task_cred(p); -	if ((info == SEND_SIG_NOINFO || -	     (!is_si_special(info) && SI_FROMUSER(info))) && +	if (si_fromuser(info) &&  	    euid != pcred->suid && euid != pcred->uid &&  	    uid  != pcred->suid && uid  != pcred->uid) {  		ret = -EPERM; @@ -1840,11 +1843,6 @@ relock:  	for (;;) {  		struct k_sigaction *ka; - -		if (unlikely(signal->group_stop_count > 0) && -		    do_signal_stop(0)) -			goto relock; -  		/*  		 * Tracing can induce an artifical signal and choose sigaction.  		 * The return value in @signr determines the default action, @@ -1856,6 +1854,10 @@ relock:  		if (unlikely(signr != 0))  			ka = return_ka;  		else { +			if (unlikely(signal->group_stop_count > 0) && +			    do_signal_stop(0)) +				goto relock; +  			signr = dequeue_signal(current, ¤t->blocked,  					       info); | 
