From: Petr Tesarik <[email protected]>
Improve UML handling of segmentation faults in kernel mode. Although
such page faults are generally caused by a kernel bug, it is annoying
if they cause an infinite loop, or panic the kernel. More importantly,
a robust implementation allows to write KUnit tests for various guard
pages, preventing potential kernel self-protection regressions.
Petr Tesarik (2):
um: do not panic on kernel mode faults
um: oops on accessing an non-present page in the vmalloc area
arch/um/kernel/trap.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
--
2.34.1
From: Petr Tesarik <[email protected]>
Do not call panic() on unrecoverable page faults in kernel mode. Although
such page faults always indicate a bug in the kernel, other architectures
prefer to kill only the current process and continue.
The new behavior is useful for testing intentional kernel mode page faults
with KUnit.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/um/kernel/trap.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 6d8ae86ae978..1124a382fd14 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -17,6 +17,14 @@
#include <os.h>
#include <skas.h>
+static void page_fault_oops(struct uml_pt_regs *regs, unsigned long address,
+ unsigned long ip)
+{
+ pr_alert("Kernel mode fault at addr 0x%lx, ip 0x%lx\n", address, ip);
+ show_regs(container_of(regs, struct pt_regs, regs));
+ make_task_dead(SIGKILL);
+}
+
/*
* Note this is constrained to return 0, -EFAULT, -EACCES, -ENOMEM by
* segv().
@@ -249,11 +257,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
else if (!is_user && arch_fixup(ip, regs))
goto out;
- if (!is_user) {
- show_regs(container_of(regs, struct pt_regs, regs));
- panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
- address, ip);
- }
+ if (!is_user)
+ page_fault_oops(regs, address, ip);
show_segv_info(regs);
--
2.34.1
From: Petr Tesarik <[email protected]>
If a segmentation fault is caused by an address in the vmalloc area, check
that the target page is present.
Currently, if the kernel hits a guard page the vmalloc area, UML assumes
that the fault is caused merely by a stale mapping and will be fixed by
flush_tlb_kernel_vm(). Of course, this will not create any mapping for a
guard page, so the faulting instruction will cause exactly the same fault
when it is executed again, effectively creating a beautiful (but useless)
infinite loop.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/um/kernel/trap.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 1124a382fd14..ca9b5fd83c52 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -214,11 +214,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
int err;
int is_write = FAULT_WRITE(fi);
unsigned long address = FAULT_ADDRESS(fi);
+ pte_t *pte;
if (!is_user && regs)
current->thread.segv_regs = container_of(regs, struct pt_regs, regs);
if (!is_user && (address >= start_vm) && (address < end_vm)) {
+ pte = virt_to_pte(&init_mm, address);
+ if (!pte_present(*pte))
+ page_fault_oops(regs, address, ip);
flush_tlb_kernel_vm();
goto out;
}
--
2.34.1
Happy New Year, everyone!
I can fully understand that you all have had other priorities around
the year end; it was no different with me. ;-)
However, may I kindly ask for some feedback on my proposed fixes?
Petr T
On Fri, 15 Dec 2023 13:14:29 +0100
Petr Tesarik <[email protected]> wrote:
> From: Petr Tesarik <[email protected]>
>
> Improve UML handling of segmentation faults in kernel mode. Although
> such page faults are generally caused by a kernel bug, it is annoying
> if they cause an infinite loop, or panic the kernel. More importantly,
> a robust implementation allows to write KUnit tests for various guard
> pages, preventing potential kernel self-protection regressions.
>
> Petr Tesarik (2):
> um: do not panic on kernel mode faults
> um: oops on accessing an non-present page in the vmalloc area
>
> arch/um/kernel/trap.c | 19 ++++++++++++++-----
> 1 file changed, 14 insertions(+), 5 deletions(-)
>
----- Ursprüngliche Mail -----
> Von: "Petr Tesarik" <[email protected]>
> An: "richard" <[email protected]>, "anton ivanov" <[email protected]>, "Johannes Berg"
> <[email protected]>, "linux-um" <[email protected]>, "linux-kernel" <[email protected]>
> CC: "Roberto Sassu" <[email protected]>, [email protected], "Petr Tesarik"
> <[email protected]>
> Gesendet: Freitag, 15. Dezember 2023 13:14:29
> Betreff: [PATCH 0/2] um: improve UML page fault handling
> From: Petr Tesarik <[email protected]>
>
> Improve UML handling of segmentation faults in kernel mode. Although
> such page faults are generally caused by a kernel bug, it is annoying
> if they cause an infinite loop, or panic the kernel. More importantly,
> a robust implementation allows to write KUnit tests for various guard
> pages, preventing potential kernel self-protection regressions.
>
> Petr Tesarik (2):
> um: do not panic on kernel mode faults
> um: oops on accessing an non-present page in the vmalloc area
I think this is a good thing to have.
For the implementation side, this needs to use the oops_* helpers
from kernel/panic.c and taint the kernel, etc...
See arch/x86/kernel/dumpstack.c die() and friends.
Thanks,
//richard
Helo Richard,
Am Fri, 5 Jan 2024 00:22:11 +0100 (CET)
schrieb Richard Weinberger <[email protected]>:
> ----- Ursprüngliche Mail -----
> > Von: "Petr Tesarik" <[email protected]>
> > An: "richard" <[email protected]>, "anton ivanov" <[email protected]>, "Johannes Berg"
> > <[email protected]>, "linux-um" <[email protected]>, "linux-kernel" <[email protected]>
> > CC: "Roberto Sassu" <[email protected]>, [email protected], "Petr Tesarik"
> > <[email protected]>
> > Gesendet: Freitag, 15. Dezember 2023 13:14:29
> > Betreff: [PATCH 0/2] um: improve UML page fault handling
>
> > From: Petr Tesarik <[email protected]>
> >
> > Improve UML handling of segmentation faults in kernel mode. Although
> > such page faults are generally caused by a kernel bug, it is annoying
> > if they cause an infinite loop, or panic the kernel. More importantly,
> > a robust implementation allows to write KUnit tests for various guard
> > pages, preventing potential kernel self-protection regressions.
> >
> > Petr Tesarik (2):
> > um: do not panic on kernel mode faults
> > um: oops on accessing an non-present page in the vmalloc area
>
> I think this is a good thing to have.
Thanks for the feedback.
> For the implementation side, this needs to use the oops_* helpers
> from kernel/panic.c and taint the kernel, etc...
Yes, I did see that coming but wanted to get some confirmation that
it's worth the effort.
> See arch/x86/kernel/dumpstack.c die() and friends.
This implementation also calls die notifiers, but AFAICS different
architectures are not very consistent in their use. Do you also
require die notifiers for the UML implementation?
Petr T
On Fri, 5 Jan 2024 07:51:09 +0100
Petr Tesařík <[email protected]> wrote:
> Helo Richard,
>
> Am Fri, 5 Jan 2024 00:22:11 +0100 (CET)
> schrieb Richard Weinberger <[email protected]>:
>
> > ----- Ursprüngliche Mail -----
> > > Von: "Petr Tesarik" <[email protected]>
> > > An: "richard" <[email protected]>, "anton ivanov" <[email protected]>, "Johannes Berg"
> > > <[email protected]>, "linux-um" <[email protected]>, "linux-kernel" <[email protected]>
> > > CC: "Roberto Sassu" <[email protected]>, [email protected], "Petr Tesarik"
> > > <[email protected]>
> > > Gesendet: Freitag, 15. Dezember 2023 13:14:29
> > > Betreff: [PATCH 0/2] um: improve UML page fault handling
> >
> > > From: Petr Tesarik <[email protected]>
> > >
> > > Improve UML handling of segmentation faults in kernel mode. Although
> > > such page faults are generally caused by a kernel bug, it is annoying
> > > if they cause an infinite loop, or panic the kernel. More importantly,
> > > a robust implementation allows to write KUnit tests for various guard
> > > pages, preventing potential kernel self-protection regressions.
> > >
> > > Petr Tesarik (2):
> > > um: do not panic on kernel mode faults
> > > um: oops on accessing an non-present page in the vmalloc area
> >
> > I think this is a good thing to have.
>
> Thanks for the feedback.
>
> > For the implementation side, this needs to use the oops_* helpers
> > from kernel/panic.c and taint the kernel, etc...
>
> Yes, I did see that coming but wanted to get some confirmation that
> it's worth the effort.
>
> > See arch/x86/kernel/dumpstack.c die() and friends.
>
> This implementation also calls die notifiers, but AFAICS different
> architectures are not very consistent in their use. Do you also
> require die notifiers for the UML implementation?
It seems I won't have time for this in the near future... Can I start
by sending a trivial patch that panics the kernel if kernel mode tries
to access a vmalloc guard page? That's something I can do immediately,
and it's still better than getting page faults in an infinite loop...
Petr T