FAILED: patch "[PATCH] signal: Correct namespace fixups of si_pid and si_uid" failed to apply to 4.9-stable tree
[email protected]
maintainerThe patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 7a0cf094944e2540758b7f957eb6846d5126f535 Mon Sep 17 00:00:00 2001
From: "Eric W. Biederman" <[email protected]>
Date: Wed, 15 May 2019 22:54:56 -0500
Subject: [PATCH] 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] 7978b567d315 ("signals: add from_ancestor_ns parameter to send_signal()")
kernel/signal.c +40 -27
@@ -1056,27 +1056,6 @@ static inline bool legacy_queue(struct sigpending *signals, int 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,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_pid =task_tgid_nr_ns (current,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 ;case (unsigned long )SEND_SIG_PRIV :clear_siginfo (&q->info);
@@ -1146,13 +1129,8 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_strucbreak ;default :copy_siginfo (&q->info, info); -if (from_ancestor_ns) - q->info.si_pid =0 ;break ; } - -userns_fixup_signal_uid (&q->info, t); - }else if (!is_si_special (info)) {if (sig >=SIGRTMIN && info->si_code !=SI_USER ) {/*
@@ -1196,6 +1174,28 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_strucreturn 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,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) && !task_pid_nr_ns (current,task_active_pid_ns (t));#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); }