提交 d831f3a3 编写于 作者: W Wetp Zhang 提交者: Caspar Zhang

mm/memory-failure: send SIGBUS(BUS_MCEERR_AR) only to current thread

fix #29415191

commit 03151c6e0b66c63c3e9980edf78c3a7a99801764 upstream

Action Required memory error should happen only when a processor is
about to access to a corrupted memory, so it's synchronous and only
affects current process/thread.

Recently commit 872e9a205c84 ("mm, memory_failure: don't send
BUS_MCEERR_AO for action required error") fixed the issue that Action
Required memory could unnecessarily send SIGBUS to the processes which
share the error memory.  But we still have another issue that we could
send SIGBUS to a wrong thread.

This is because collect_procs() and task_early_kill() fails to add the
current process to "to-kill" list.  So this patch is suggesting to fix
it.  With this fix, SIGBUS(BUS_MCEERR_AR) is never sent to non-current
process/thread.
Signed-off-by: NNaoya Horiguchi <naoya.horiguchi@nec.com>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Acked-by: NTony Luck <tony.luck@intel.com>
Acked-by: NPankaj Gupta <pankaj.gupta.linux@gmail.com>
Link: http://lkml.kernel.org/r/1591321039-22141-3-git-send-email-naoya.horiguchi@nec.comSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: NWetp Zhang <wetp.zy@linux.alibaba.com>
Reviewed-by: NArtie Ding <artie.ding@linux.alibaba.com>
上级 de9dc394
...@@ -215,15 +215,13 @@ static int kill_proc(struct to_kill *tk, unsigned long pfn, int flags) ...@@ -215,15 +215,13 @@ static int kill_proc(struct to_kill *tk, unsigned long pfn, int flags)
short addr_lsb = tk->size_shift; short addr_lsb = tk->size_shift;
int ret = 0; int ret = 0;
if ((t->mm == current->mm) || !(flags & MF_ACTION_REQUIRED))
pr_err("Memory failure: %#lx: Killing %s:%d due to hardware memory corruption\n", pr_err("Memory failure: %#lx: Killing %s:%d due to hardware memory corruption\n",
pfn, t->comm, t->pid); pfn, t->comm, t->pid);
if (flags & MF_ACTION_REQUIRED) { if (flags & MF_ACTION_REQUIRED) {
if (t->mm == current->mm) WARN_ON_ONCE(t != current);
ret = force_sig_mceerr(BUS_MCEERR_AR, ret = force_sig_mceerr(BUS_MCEERR_AR,
(void __user *)tk->addr, addr_lsb, current); (void __user *)tk->addr, addr_lsb, current);
/* send no signal to non-current processes */
} else { } else {
/* /*
* Don't use force here, it's convenient if the signal * Don't use force here, it's convenient if the signal
...@@ -421,6 +419,9 @@ static struct task_struct *find_early_kill_thread(struct task_struct *tsk) ...@@ -421,6 +419,9 @@ static struct task_struct *find_early_kill_thread(struct task_struct *tsk)
* to be signaled when some page under the process is hwpoisoned. * to be signaled when some page under the process is hwpoisoned.
* Return task_struct of the dedicated thread (main thread unless explicitly * Return task_struct of the dedicated thread (main thread unless explicitly
* specified) if the process is "early kill," and otherwise returns NULL. * specified) if the process is "early kill," and otherwise returns NULL.
*
* Note that the above is true for Action Optional case, but not for Action
* Required case where SIGBUS should sent only to the current thread.
*/ */
static struct task_struct *task_early_kill(struct task_struct *tsk, static struct task_struct *task_early_kill(struct task_struct *tsk,
int force_early) int force_early)
...@@ -428,8 +429,16 @@ static struct task_struct *task_early_kill(struct task_struct *tsk, ...@@ -428,8 +429,16 @@ static struct task_struct *task_early_kill(struct task_struct *tsk,
struct task_struct *t; struct task_struct *t;
if (!tsk->mm) if (!tsk->mm)
return NULL; return NULL;
if (force_early) if (force_early) {
return tsk; /*
* Comparing ->mm here because current task might represent
* a subthread, while tsk always points to the main thread.
*/
if (tsk->mm == current->mm)
return current;
else
return NULL;
}
t = find_early_kill_thread(tsk); t = find_early_kill_thread(tsk);
if (t) if (t)
return t; return t;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册