mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	signal: Correct namespace fixups of si_pid and si_uid
The function send_signal was split from __send_signal so that it would be possible to bypass the namespace logic based upon current[1]. As it turns out the si_pid and the si_uid fixup are both inappropriate in the case of kill_pid_usb_asyncio so move that logic into send_signal. It is difficult to arrange but possible for a signal with an si_code of SI_TIMER or SI_SIGIO to be sent across namespace boundaries. In which case tests for when it is ok to change si_pid and si_uid based on SI_FROMUSER are incorrect. Replace the use of SI_FROMUSER with a new test has_si_pid_and_used based on siginfo_layout. Now that the uid fixup is no longer present after expanding SEND_SIG_NOINFO properly calculate the si_uid that the target task needs to read. [1]7978b567d3("signals: add from_ancestor_ns parameter to send_signal()") Cc: stable@vger.kernel.org Fixes:6588c1e3ff("signals: SI_USER: Masquerade si_pid when crossing pid ns boundary") Fixes:6b550f9495("user namespace: make signal.c respect user namespaces") Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
		
							parent
							
								
									70f1b0d34b
								
							
						
					
					
						commit
						7a0cf09494
					
				
					 1 changed files with 40 additions and 27 deletions
				
			
		| 
						 | 
					@ -1056,27 +1056,6 @@ static inline bool legacy_queue(struct sigpending *signals, int sig)
 | 
				
			||||||
	return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
 | 
						return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_USER_NS
 | 
					 | 
				
			||||||
static inline void userns_fixup_signal_uid(struct kernel_siginfo *info, struct task_struct *t)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (current_user_ns() == task_cred_xxx(t, user_ns))
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (SI_FROMKERNEL(info))
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rcu_read_lock();
 | 
					 | 
				
			||||||
	info->si_uid = from_kuid_munged(task_cred_xxx(t, user_ns),
 | 
					 | 
				
			||||||
					make_kuid(current_user_ns(), info->si_uid));
 | 
					 | 
				
			||||||
	rcu_read_unlock();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
static inline void userns_fixup_signal_uid(struct kernel_siginfo *info, struct task_struct *t)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struct *t,
 | 
					static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struct *t,
 | 
				
			||||||
			enum pid_type type, int from_ancestor_ns)
 | 
								enum pid_type type, int from_ancestor_ns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1134,7 +1113,11 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
 | 
				
			||||||
			q->info.si_code = SI_USER;
 | 
								q->info.si_code = SI_USER;
 | 
				
			||||||
			q->info.si_pid = task_tgid_nr_ns(current,
 | 
								q->info.si_pid = task_tgid_nr_ns(current,
 | 
				
			||||||
							task_active_pid_ns(t));
 | 
												task_active_pid_ns(t));
 | 
				
			||||||
			q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
 | 
								rcu_read_lock();
 | 
				
			||||||
 | 
								q->info.si_uid =
 | 
				
			||||||
 | 
									from_kuid_munged(task_cred_xxx(t, user_ns),
 | 
				
			||||||
 | 
											 current_uid());
 | 
				
			||||||
 | 
								rcu_read_unlock();
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case (unsigned long) SEND_SIG_PRIV:
 | 
							case (unsigned long) SEND_SIG_PRIV:
 | 
				
			||||||
			clear_siginfo(&q->info);
 | 
								clear_siginfo(&q->info);
 | 
				
			||||||
| 
						 | 
					@ -1146,13 +1129,8 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			copy_siginfo(&q->info, info);
 | 
								copy_siginfo(&q->info, info);
 | 
				
			||||||
			if (from_ancestor_ns)
 | 
					 | 
				
			||||||
				q->info.si_pid = 0;
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		userns_fixup_signal_uid(&q->info, t);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	} else if (!is_si_special(info)) {
 | 
						} else if (!is_si_special(info)) {
 | 
				
			||||||
		if (sig >= SIGRTMIN && info->si_code != SI_USER) {
 | 
							if (sig >= SIGRTMIN && info->si_code != SI_USER) {
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
| 
						 | 
					@ -1196,6 +1174,28 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool has_si_pid_and_uid(struct kernel_siginfo *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool ret = false;
 | 
				
			||||||
 | 
						switch (siginfo_layout(info->si_signo, info->si_code)) {
 | 
				
			||||||
 | 
						case SIL_KILL:
 | 
				
			||||||
 | 
						case SIL_CHLD:
 | 
				
			||||||
 | 
						case SIL_RT:
 | 
				
			||||||
 | 
							ret = true;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SIL_TIMER:
 | 
				
			||||||
 | 
						case SIL_POLL:
 | 
				
			||||||
 | 
						case SIL_FAULT:
 | 
				
			||||||
 | 
						case SIL_FAULT_MCEERR:
 | 
				
			||||||
 | 
						case SIL_FAULT_BNDERR:
 | 
				
			||||||
 | 
						case SIL_FAULT_PKUERR:
 | 
				
			||||||
 | 
						case SIL_SYS:
 | 
				
			||||||
 | 
							ret = false;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int send_signal(int sig, struct kernel_siginfo *info, struct task_struct *t,
 | 
					static int send_signal(int sig, struct kernel_siginfo *info, struct task_struct *t,
 | 
				
			||||||
			enum pid_type type)
 | 
								enum pid_type type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1205,7 +1205,20 @@ static int send_signal(int sig, struct kernel_siginfo *info, struct task_struct
 | 
				
			||||||
	from_ancestor_ns = si_fromuser(info) &&
 | 
						from_ancestor_ns = si_fromuser(info) &&
 | 
				
			||||||
			   !task_pid_nr_ns(current, task_active_pid_ns(t));
 | 
								   !task_pid_nr_ns(current, task_active_pid_ns(t));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
						if (!is_si_special(info) && has_si_pid_and_uid(info)) {
 | 
				
			||||||
 | 
							struct user_namespace *t_user_ns;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rcu_read_lock();
 | 
				
			||||||
 | 
							t_user_ns = task_cred_xxx(t, user_ns);
 | 
				
			||||||
 | 
							if (current_user_ns() != t_user_ns) {
 | 
				
			||||||
 | 
								kuid_t uid = make_kuid(current_user_ns(), info->si_uid);
 | 
				
			||||||
 | 
								info->si_uid = from_kuid_munged(t_user_ns, uid);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!task_pid_nr_ns(current, task_active_pid_ns(t)))
 | 
				
			||||||
 | 
								info->si_pid = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return __send_signal(sig, info, t, type, from_ancestor_ns);
 | 
						return __send_signal(sig, info, t, type, from_ancestor_ns);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue