arch/x86/include/asm/bug.h | 1 + arch/x86/kernel/traps.c | 2 +- arch/x86/mm/extable.c | 7 ++----- 3 files changed, 4 insertions(+), 6 deletions(-)
The commit 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
implemented __WARN_printf(), which changed the mechanism to use UD1
instead of UD2. However, it only handles the trap in the runtime IDT
handler, while the early booting IDT handler lacks this handling. As a
result, the usage of WARN() before the runtime IDT setup can lead to
kernel crashes. Since KMSAN is enabled after the runtime IDT setup, it
is safe to use handle_bug() directly in early_fixup_exception() to
address this issue.
Fixes: 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
---
arch/x86/include/asm/bug.h | 1 +
arch/x86/kernel/traps.c | 2 +-
arch/x86/mm/extable.c | 7 ++-----
3 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
index 9b4e04690e1a..23e4b235461d 100644
--- a/arch/x86/include/asm/bug.h
+++ b/arch/x86/include/asm/bug.h
@@ -153,6 +153,7 @@ struct arch_va_list {
struct sysv_va_list args;
};
extern void *__warn_args(struct arch_va_list *args, struct pt_regs *regs);
+extern noinstr bool handle_bug(struct pt_regs *regs);
#endif /* __ASSEMBLY__ */
#define __WARN_bug_entry(flags, format) ({ \
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index bcf1dedc1d00..aca1eca5daff 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -397,7 +397,7 @@ static inline void handle_invalid_op(struct pt_regs *regs)
ILL_ILLOPN, error_get_trap_addr(regs));
}
-static noinstr bool handle_bug(struct pt_regs *regs)
+noinstr bool handle_bug(struct pt_regs *regs)
{
unsigned long addr = regs->ip;
bool handled = false;
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 2fdc1f1f5adb..6b9ff1c6cafa 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -411,14 +411,11 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
return;
if (trapnr == X86_TRAP_UD) {
- if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) {
- /* Skip the ud2. */
- regs->ip += LEN_UD2;
+ if (handle_bug(regs))
return;
- }
/*
- * If this was a BUG and report_bug returns or if this
+ * If this was a BUG and handle_bug returns or if this
* was just a normal #UD, we want to continue onward and
* crash.
*/
--
2.31.1
Hi Hou,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.19-rc4 next-20260109]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Hou-Wenlong/x86_64-bug-Handle-__WARN_printf-trap-in-early_fixup_exception/20260109-204012
base: linus/master
patch link: https://lore.kernel.org/r/97dd5c5b5e92d48ffbc95fb1357dfbbbf0d12a1e.1767960698.git.houwenlong.hwl%40antgroup.com
patch subject: [PATCH] x86_64/bug: Handle __WARN_printf() trap in early_fixup_exception()
config: i386-allnoconfig-bpf (https://download.01.org/0day-ci/archive/20260110/202601100329.ndS6mKRm-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260110/202601100329.ndS6mKRm-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202601100329.ndS6mKRm-lkp@intel.com/
All errors (new ones prefixed by >>):
>> arch/x86/mm/extable.c:414:7: error: call to undeclared function 'handle_bug'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
414 | if (handle_bug(regs))
| ^
1 error generated.
vim +/handle_bug +414 arch/x86/mm/extable.c
376
377 /* Restricted version used during very early boot */
378 void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
379 {
380 /* Ignore early NMIs. */
381 if (trapnr == X86_TRAP_NMI)
382 return;
383
384 if (early_recursion_flag > 2)
385 goto halt_loop;
386
387 /*
388 * Old CPUs leave the high bits of CS on the stack
389 * undefined. I'm not sure which CPUs do this, but at least
390 * the 486 DX works this way.
391 * Xen pv domains are not using the default __KERNEL_CS.
392 */
393 if (!xen_pv_domain() && regs->cs != __KERNEL_CS)
394 goto fail;
395
396 /*
397 * The full exception fixup machinery is available as soon as
398 * the early IDT is loaded. This means that it is the
399 * responsibility of extable users to either function correctly
400 * when handlers are invoked early or to simply avoid causing
401 * exceptions before they're ready to handle them.
402 *
403 * This is better than filtering which handlers can be used,
404 * because refusing to call a handler here is guaranteed to
405 * result in a hard-to-debug panic.
406 *
407 * Keep in mind that not all vectors actually get here. Early
408 * page faults, for example, are special.
409 */
410 if (fixup_exception(regs, trapnr, regs->orig_ax, 0))
411 return;
412
413 if (trapnr == X86_TRAP_UD) {
> 414 if (handle_bug(regs))
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
The commit 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
implemented __WARN_printf(), which changed the mechanism to use UD1
instead of UD2. However, it only handles the trap in the runtime IDT
handler, while the early booting IDT handler lacks this handling. As a
result, the usage of WARN() before the runtime IDT setup can lead to
kernel crashes. Since KMSAN is enabled after the runtime IDT setup, it
is safe to use handle_bug() directly in early_fixup_exception() to
address this issue.
Fixes: 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
---
arch/x86/include/asm/traps.h | 2 ++
arch/x86/kernel/traps.c | 2 +-
arch/x86/mm/extable.c | 7 ++-----
3 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index 869b88061801..3f24cc472ce9 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -25,6 +25,8 @@ extern int ibt_selftest_noendbr(void);
void handle_invalid_op(struct pt_regs *regs);
#endif
+noinstr bool handle_bug(struct pt_regs *regs);
+
static inline int get_si_code(unsigned long condition)
{
if (condition & DR_STEP)
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index bcf1dedc1d00..aca1eca5daff 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -397,7 +397,7 @@ static inline void handle_invalid_op(struct pt_regs *regs)
ILL_ILLOPN, error_get_trap_addr(regs));
}
-static noinstr bool handle_bug(struct pt_regs *regs)
+noinstr bool handle_bug(struct pt_regs *regs)
{
unsigned long addr = regs->ip;
bool handled = false;
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 2fdc1f1f5adb..6b9ff1c6cafa 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -411,14 +411,11 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
return;
if (trapnr == X86_TRAP_UD) {
- if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) {
- /* Skip the ud2. */
- regs->ip += LEN_UD2;
+ if (handle_bug(regs))
return;
- }
/*
- * If this was a BUG and report_bug returns or if this
+ * If this was a BUG and handle_bug returns or if this
* was just a normal #UD, we want to continue onward and
* crash.
*/
base-commit: b7dccac786071bba98b0d834c517fd44a22c50f9
--
2.31.1
On Sat, Jan 10, 2026 at 11:47:37AM +0800, Hou Wenlong wrote:
> The commit 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
> implemented __WARN_printf(), which changed the mechanism to use UD1
> instead of UD2. However, it only handles the trap in the runtime IDT
> handler, while the early booting IDT handler lacks this handling. As a
> result, the usage of WARN() before the runtime IDT setup can lead to
> kernel crashes.
Urgh, indeed. Clearly I don't see many early WARNs :/
> Since KMSAN is enabled after the runtime IDT setup, it
> is safe to use handle_bug() directly in early_fixup_exception() to
> address this issue.
I'm not sure I understand this. Should it not be that KMSAN is enabled
*before* early IDT to make this a non-issue?
> Fixes: 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
> Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
> ---
> arch/x86/include/asm/traps.h | 2 ++
> arch/x86/kernel/traps.c | 2 +-
> arch/x86/mm/extable.c | 7 ++-----
> 3 files changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
> index 869b88061801..3f24cc472ce9 100644
> --- a/arch/x86/include/asm/traps.h
> +++ b/arch/x86/include/asm/traps.h
> @@ -25,6 +25,8 @@ extern int ibt_selftest_noendbr(void);
> void handle_invalid_op(struct pt_regs *regs);
> #endif
>
> +noinstr bool handle_bug(struct pt_regs *regs);
> +
> static inline int get_si_code(unsigned long condition)
> {
> if (condition & DR_STEP)
> diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> index bcf1dedc1d00..aca1eca5daff 100644
> --- a/arch/x86/kernel/traps.c
> +++ b/arch/x86/kernel/traps.c
> @@ -397,7 +397,7 @@ static inline void handle_invalid_op(struct pt_regs *regs)
> ILL_ILLOPN, error_get_trap_addr(regs));
> }
>
> -static noinstr bool handle_bug(struct pt_regs *regs)
> +noinstr bool handle_bug(struct pt_regs *regs)
> {
> unsigned long addr = regs->ip;
> bool handled = false;
> diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
> index 2fdc1f1f5adb..6b9ff1c6cafa 100644
> --- a/arch/x86/mm/extable.c
> +++ b/arch/x86/mm/extable.c
> @@ -411,14 +411,11 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
> return;
>
> if (trapnr == X86_TRAP_UD) {
> - if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) {
> - /* Skip the ud2. */
> - regs->ip += LEN_UD2;
> + if (handle_bug(regs))
> return;
> - }
>
> /*
> - * If this was a BUG and report_bug returns or if this
> + * If this was a BUG and handle_bug returns or if this
> * was just a normal #UD, we want to continue onward and
> * crash.
> */
>
> base-commit: b7dccac786071bba98b0d834c517fd44a22c50f9
> --
> 2.31.1
>
On Mon, Jan 12, 2026 at 08:44:28AM +0100, Peter Zijlstra wrote:
> On Sat, Jan 10, 2026 at 11:47:37AM +0800, Hou Wenlong wrote:
> > The commit 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
> > implemented __WARN_printf(), which changed the mechanism to use UD1
> > instead of UD2. However, it only handles the trap in the runtime IDT
> > handler, while the early booting IDT handler lacks this handling. As a
> > result, the usage of WARN() before the runtime IDT setup can lead to
> > kernel crashes.
>
> Urgh, indeed. Clearly I don't see many early WARNs :/
>
> > Since KMSAN is enabled after the runtime IDT setup, it
> > is safe to use handle_bug() directly in early_fixup_exception() to
> > address this issue.
>
> I'm not sure I understand this. Should it not be that KMSAN is enabled
> *before* early IDT to make this a non-issue?
>
> > Fixes: 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
> > Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
> > ---
> > arch/x86/include/asm/traps.h | 2 ++
> > arch/x86/kernel/traps.c | 2 +-
> > arch/x86/mm/extable.c | 7 ++-----
> > 3 files changed, 5 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
> > index 869b88061801..3f24cc472ce9 100644
> > --- a/arch/x86/include/asm/traps.h
> > +++ b/arch/x86/include/asm/traps.h
> > @@ -25,6 +25,8 @@ extern int ibt_selftest_noendbr(void);
> > void handle_invalid_op(struct pt_regs *regs);
> > #endif
> >
> > +noinstr bool handle_bug(struct pt_regs *regs);
> > +
> > static inline int get_si_code(unsigned long condition)
> > {
> > if (condition & DR_STEP)
> > diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> > index bcf1dedc1d00..aca1eca5daff 100644
> > --- a/arch/x86/kernel/traps.c
> > +++ b/arch/x86/kernel/traps.c
> > @@ -397,7 +397,7 @@ static inline void handle_invalid_op(struct pt_regs *regs)
> > ILL_ILLOPN, error_get_trap_addr(regs));
> > }
> >
> > -static noinstr bool handle_bug(struct pt_regs *regs)
> > +noinstr bool handle_bug(struct pt_regs *regs)
> > {
> > unsigned long addr = regs->ip;
> > bool handled = false;
> > diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
> > index 2fdc1f1f5adb..6b9ff1c6cafa 100644
> > --- a/arch/x86/mm/extable.c
> > +++ b/arch/x86/mm/extable.c
> > @@ -411,14 +411,11 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
> > return;
> >
> > if (trapnr == X86_TRAP_UD) {
> > - if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) {
> > - /* Skip the ud2. */
> > - regs->ip += LEN_UD2;
> > + if (handle_bug(regs))
> > return;
> > - }
> >
> > /*
> > - * If this was a BUG and report_bug returns or if this
> > + * If this was a BUG and handle_bug returns or if this
> > * was just a normal #UD, we want to continue onward and
> > * crash.
> > */
> >
> > base-commit: b7dccac786071bba98b0d834c517fd44a22c50f9
> > --
> > 2.31.1
> >
Hi, Peter.
I received a kernel test robot build failure message regarding this
patch, but I noticed that you queued the v1 version instead of the v2
version in your queue tree[0]. I ran the test config file with the v2
version, and it should be fine.
[0]: https://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git/commit/?h=x86/urgent&id=695d896472d6543523de43110b0016b8b4469643
Thanks!
On Mon, Jan 12, 2026 at 08:44:28AM +0100, Peter Zijlstra wrote:
> On Sat, Jan 10, 2026 at 11:47:37AM +0800, Hou Wenlong wrote:
> > The commit 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
> > implemented __WARN_printf(), which changed the mechanism to use UD1
> > instead of UD2. However, it only handles the trap in the runtime IDT
> > handler, while the early booting IDT handler lacks this handling. As a
> > result, the usage of WARN() before the runtime IDT setup can lead to
> > kernel crashes.
>
> Urgh, indeed. Clearly I don't see many early WARNs :/
>
Uh, I found this accidentally while I was trying to clean up the
early_ioremap debug printing, where it uses WARN() for dumpstack.
> > Since KMSAN is enabled after the runtime IDT setup, it
> > is safe to use handle_bug() directly in early_fixup_exception() to
> > address this issue.
>
> I'm not sure I understand this. Should it not be that KMSAN is enabled
> *before* early IDT to make this a non-issue?
>
I see that handle_bug() would call kmsan_unpoison_entry_regs(), and I
assume that it should be a NOP before kmsan_init_runtime(). Therefore, I
think it's safe to use handle_bug() directly in early_fixup_exception().
Additionally, I note that kmsan_init_runtime() is called after
trap_init(), which is why I described the commit message this way.
Thanks!
> > Fixes: 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
> > Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
> > ---
> > arch/x86/include/asm/traps.h | 2 ++
> > arch/x86/kernel/traps.c | 2 +-
> > arch/x86/mm/extable.c | 7 ++-----
> > 3 files changed, 5 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
> > index 869b88061801..3f24cc472ce9 100644
> > --- a/arch/x86/include/asm/traps.h
> > +++ b/arch/x86/include/asm/traps.h
> > @@ -25,6 +25,8 @@ extern int ibt_selftest_noendbr(void);
> > void handle_invalid_op(struct pt_regs *regs);
> > #endif
> >
> > +noinstr bool handle_bug(struct pt_regs *regs);
> > +
> > static inline int get_si_code(unsigned long condition)
> > {
> > if (condition & DR_STEP)
> > diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> > index bcf1dedc1d00..aca1eca5daff 100644
> > --- a/arch/x86/kernel/traps.c
> > +++ b/arch/x86/kernel/traps.c
> > @@ -397,7 +397,7 @@ static inline void handle_invalid_op(struct pt_regs *regs)
> > ILL_ILLOPN, error_get_trap_addr(regs));
> > }
> >
> > -static noinstr bool handle_bug(struct pt_regs *regs)
> > +noinstr bool handle_bug(struct pt_regs *regs)
> > {
> > unsigned long addr = regs->ip;
> > bool handled = false;
> > diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
> > index 2fdc1f1f5adb..6b9ff1c6cafa 100644
> > --- a/arch/x86/mm/extable.c
> > +++ b/arch/x86/mm/extable.c
> > @@ -411,14 +411,11 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
> > return;
> >
> > if (trapnr == X86_TRAP_UD) {
> > - if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) {
> > - /* Skip the ud2. */
> > - regs->ip += LEN_UD2;
> > + if (handle_bug(regs))
> > return;
> > - }
> >
> > /*
> > - * If this was a BUG and report_bug returns or if this
> > + * If this was a BUG and handle_bug returns or if this
> > * was just a normal #UD, we want to continue onward and
> > * crash.
> > */
> >
> > base-commit: b7dccac786071bba98b0d834c517fd44a22c50f9
> > --
> > 2.31.1
> >
© 2016 - 2026 Red Hat, Inc.