From: Tony Luck <tony.luck@intel.com>
To: Borislav Petkov <bp@alien8.de>
Cc: Tony Luck <tony.luck@intel.com>,
x86@kernel.org, Andrew Morton <akpm@linux-foundation.org>,
Peter Zijlstra <peterz@infradead.org>,
Darren Hart <dvhart@infradead.org>,
Andy Lutomirski <luto@kernel.org>,
linux-kernel@vger.kernel.org, linux-edac@vger.kernel.org,
linux-mm@kvack.org
Subject: [PATCH v2 1/3] x86/mce: Avoid infinite loop for copy from user recovery
Date: Mon, 11 Jan 2021 13:44:50 -0800 [thread overview]
Message-ID: <20210111214452.1826-2-tony.luck@intel.com> (raw)
In-Reply-To: <20210111214452.1826-1-tony.luck@intel.com>
Recovery action when get_user() triggers a machine check uses the fixup
path to make get_user() return -EFAULT. Also queue_task_work() sets up
so that kill_me_maybe() will be called on return to user mode to send a
SIGBUS to the current process.
But there are places in the kernel where the code assumes that this
EFAULT return was simply because of a page fault. The code takes some
action to fix that, and then retries the access. This results in a second
machine check.
While processing this second machine check queue_task_work() is called
again. But since this uses the same callback_head structure that
was used in the first call, the net result is an entry on the
current->task_works list that points to itself. When task_work_run()
is called it loops forever in this code:
do {
next = work->next;
work->func(work);
work = next;
cond_resched();
} while (work);
Add a "mce_busy" flag bit to detect this situation and panic
when it happens.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
arch/x86/kernel/cpu/mce/core.c | 7 ++++++-
include/linux/sched.h | 3 ++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
index 13d3f1cbda17..1bf11213e093 100644
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -1246,6 +1246,7 @@ static void kill_me_maybe(struct callback_head *cb)
struct task_struct *p = container_of(cb, struct task_struct, mce_kill_me);
int flags = MF_ACTION_REQUIRED;
+ p->mce_busy = 0;
pr_err("Uncorrected hardware memory error in user-access at %llx", p->mce_addr);
if (!p->mce_ripv)
@@ -1268,6 +1269,7 @@ static void kill_me_maybe(struct callback_head *cb)
static void queue_task_work(struct mce *m, int kill_current_task)
{
+ current->mce_busy = 1;
current->mce_addr = m->addr;
current->mce_kflags = m->kflags;
current->mce_ripv = !!(m->mcgstatus & MCG_STATUS_RIPV);
@@ -1431,8 +1433,11 @@ noinstr void do_machine_check(struct pt_regs *regs)
mce_panic("Failed kernel mode recovery", &m, msg);
}
- if (m.kflags & MCE_IN_KERNEL_COPYIN)
+ if (m.kflags & MCE_IN_KERNEL_COPYIN) {
+ if (current->mce_busy)
+ mce_panic("Multiple copyin", &m, msg);
queue_task_work(&m, kill_current_task);
+ }
}
out:
mce_wrmsrl(MSR_IA32_MCG_STATUS, 0);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6e3a5eeec509..a763a76eac57 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1360,7 +1360,8 @@ struct task_struct {
u64 mce_addr;
__u64 mce_ripv : 1,
mce_whole_page : 1,
- __mce_reserved : 62;
+ mce_busy : 1,
+ __mce_reserved : 61;
struct callback_head mce_kill_me;
#endif
--
2.21.1
next prev parent reply other threads:[~2021-01-11 21:46 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-08 22:22 [PATCH 0/2] Fix infinite machine check loop in futex_wait_setup() Tony Luck
2021-01-08 22:22 ` [PATCH 1/2] x86/mce: Avoid infinite loop for copy from user recovery Tony Luck
2021-01-08 22:22 ` [PATCH 2/2] futex, x86/mce: Avoid double machine checks Tony Luck
2021-01-08 22:47 ` Peter Zijlstra
2021-01-08 23:08 ` Luck, Tony
2021-01-08 23:14 ` Peter Zijlstra
2021-01-08 23:20 ` Luck, Tony
2021-01-11 21:44 ` [PATCH v2 0/3] Fix infinite machine check loop in futex_wait_setup() Tony Luck
2021-01-11 21:44 ` Tony Luck [this message]
2021-01-11 22:11 ` [PATCH v2 1/3] x86/mce: Avoid infinite loop for copy from user recovery Andy Lutomirski
2021-01-11 22:20 ` Luck, Tony
2021-01-12 17:00 ` Andy Lutomirski
2021-01-12 17:16 ` Luck, Tony
2021-01-12 17:21 ` Andy Lutomirski
2021-01-12 18:23 ` Luck, Tony
2021-01-12 18:57 ` Andy Lutomirski
2021-01-12 20:52 ` Luck, Tony
2021-01-12 22:04 ` Andy Lutomirski
2021-01-13 1:50 ` Luck, Tony
2021-01-13 4:15 ` Andy Lutomirski
2021-01-13 10:00 ` Borislav Petkov
2021-01-13 16:06 ` Luck, Tony
2021-01-13 16:19 ` Borislav Petkov
2021-01-13 16:32 ` Luck, Tony
2021-01-13 17:35 ` Borislav Petkov
2021-01-14 20:22 ` Borislav Petkov
2021-01-14 21:05 ` Luck, Tony
2021-01-11 21:44 ` [PATCH v2 2/3] x86/mce: Add new return value to get_user() for machine check Tony Luck
2021-01-11 21:44 ` [PATCH v2 3/3] futex, x86/mce: Avoid double machine checks Tony Luck
2021-01-14 17:22 ` [PATCH v2 0/3] Fix infinite machine check loop in futex_wait_setup() Andy Lutomirski
2021-01-15 0:38 ` [PATCH v3] x86/mce: Avoid infinite loop for copy from user recovery Tony Luck
2021-01-15 15:27 ` Borislav Petkov
2021-01-15 19:34 ` Luck, Tony
2021-01-15 20:51 ` [PATCH v4] " Luck, Tony
2021-01-15 23:23 ` Luck, Tony
2021-01-19 10:56 ` Borislav Petkov
2021-01-19 23:57 ` Luck, Tony
2021-01-20 12:18 ` Borislav Petkov
2021-01-20 17:17 ` Luck, Tony
2021-01-21 21:09 ` Luck, Tony
2021-01-25 22:55 ` [PATCH v5] " Luck, Tony
2021-01-26 11:03 ` Borislav Petkov
2021-01-26 22:36 ` Luck, Tony
2021-01-28 17:57 ` Borislav Petkov
2021-02-01 18:58 ` Luck, Tony
2021-02-02 11:01 ` Borislav Petkov
2021-02-02 16:04 ` Luck, Tony
2021-02-02 21:06 ` Borislav Petkov
2021-02-02 22:12 ` Luck, Tony
2021-01-18 15:39 ` [PATCH v3] " Borislav Petkov
2021-07-06 19:06 [PATCH 0/3] More machine check recovery fixes Tony Luck
2021-08-18 0:29 ` [PATCH v2 " Tony Luck
2021-08-18 0:29 ` [PATCH v2 1/3] x86/mce: Avoid infinite loop for copy from user recovery Tony Luck
2021-08-20 17:31 ` Borislav Petkov
2021-08-20 18:59 ` Luck, Tony
2021-08-20 19:27 ` Borislav Petkov
2021-08-20 20:23 ` Luck, Tony
2021-08-21 4:51 ` Tony Luck
2021-08-21 21:51 ` Al Viro
2021-08-22 14:36 ` Borislav Petkov
2021-08-20 20:33 ` Luck, Tony
2021-08-22 14:46 ` Borislav Petkov
2021-08-23 15:24 ` Luck, Tony
2021-09-13 9:24 ` Borislav Petkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210111214452.1826-2-tony.luck@intel.com \
--to=tony.luck@intel.com \
--cc=akpm@linux-foundation.org \
--cc=bp@alien8.de \
--cc=dvhart@infradead.org \
--cc=linux-edac@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=luto@kernel.org \
--cc=peterz@infradead.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).