* Kees Cook <keescook@xxxxxxxxxxxx> wrote: > On Wed, Nov 27, 2019 at 08:19:30AM -0000, tip-bot2 for Andy Lutomirski wrote: > > The following commit has been merged into the x86/urgent branch of tip: > > > > Commit-ID: b09511c253e5c739a60952b97c071a93e92b2e88 > > Gitweb: https://git.kernel.org/tip/b09511c253e5c739a60952b97c071a93e92b2e88 > > Author: Andy Lutomirski <luto@xxxxxxxxxx> > > AuthorDate: Sun, 24 Nov 2019 21:18:04 -08:00 > > Committer: Ingo Molnar <mingo@xxxxxxxxxx> > > CommitterDate: Tue, 26 Nov 2019 21:53:34 +01:00 > > > > lkdtm: Add a DOUBLE_FAULT crash type on x86 > > > > The DOUBLE_FAULT crash does INT $8, which is a decent approximation > > of a double fault. This is useful for testing the double fault > > handling. Use it like: > > > > Signed-off-by: Andy Lutomirski <luto@xxxxxxxxxx> > > Cc: Kees Cook <keescook@xxxxxxxxxxxx> > > Cc: Arnd Bergmann <arnd@xxxxxxxx> > > Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> > > Cc: Borislav Petkov <bp@xxxxxxxxx> > > Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx> > > Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > > Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> > > Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx> > > --- > > drivers/misc/lkdtm/bugs.c | 39 +++++++++++++++++++++++++++++++++++++- > > drivers/misc/lkdtm/core.c | 3 +++- > > drivers/misc/lkdtm/lkdtm.h | 3 +++- > > 3 files changed, 45 insertions(+) > > > > diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c > > index 7284a22..a4fdad0 100644 > > --- a/drivers/misc/lkdtm/bugs.c > > +++ b/drivers/misc/lkdtm/bugs.c > > @@ -12,6 +12,10 @@ > > #include <linux/sched/task_stack.h> > > #include <linux/uaccess.h> > > > > +#ifdef CONFIG_X86_32 > > +#include <asm/desc.h> > > +#endif > > + > > struct lkdtm_list { > > struct list_head node; > > }; > > @@ -337,3 +341,38 @@ void lkdtm_UNSET_SMEP(void) > > pr_err("FAIL: this test is x86_64-only\n"); > > #endif > > } > > + > > +#ifdef CONFIG_X86_32 > > +void lkdtm_DOUBLE_FAULT(void) > > +{ > > + /* > > + * Trigger #DF by setting the stack limit to zero. This clobbers > > + * a GDT TLS slot, which is okay because the current task will die > > + * anyway due to the double fault. > > + */ > > + struct desc_struct d = { > > + .type = 3, /* expand-up, writable, accessed data */ > > + .p = 1, /* present */ > > + .d = 1, /* 32-bit */ > > + .g = 0, /* limit in bytes */ > > + .s = 1, /* not system */ > > + }; > > + > > + local_irq_disable(); > > + write_gdt_entry(get_cpu_gdt_rw(smp_processor_id()), > > + GDT_ENTRY_TLS_MIN, &d, DESCTYPE_S); > > + > > + /* > > + * Put our zero-limit segment in SS and then trigger a fault. The > > + * 4-byte access to (%esp) will fault with #SS, and the attempt to > > + * deliver the fault will recursively cause #SS and result in #DF. > > + * This whole process happens while NMIs and MCEs are blocked by the > > + * MOV SS window. This is nice because an NMI with an invalid SS > > + * would also double-fault, resulting in the NMI or MCE being lost. > > + */ > > + asm volatile ("movw %0, %%ss; addl $0, (%%esp)" :: > > + "r" ((unsigned short)(GDT_ENTRY_TLS_MIN << 3))); > > + > > + panic("tried to double fault but didn't die\n"); > > I'll modify this in some later patches, but I prefer the #ifdef inside > the function so that all tests are visible on all > architectures/configurations. And it should not panic on a test failure, > it should continue (see the others) with something like: > > pr_err("FAIL: did not double fault!\n"); > > E.g. an external system monitor would see the double-fault and the panic as > both causing a system reboot, but only the double-fault should do that. > > > +} > > +#endif > > diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c > > index cbc4c90..ee0d6e7 100644 > > --- a/drivers/misc/lkdtm/core.c > > +++ b/drivers/misc/lkdtm/core.c > > @@ -171,6 +171,9 @@ static const struct crashtype crashtypes[] = { > > CRASHTYPE(USERCOPY_KERNEL_DS), > > CRASHTYPE(STACKLEAK_ERASING), > > CRASHTYPE(CFI_FORWARD_PROTO), > > +#ifdef CONFIG_X86_32 > > + CRASHTYPE(DOUBLE_FAULT), > > +#endif > > And then ifdefs aren't needed here either. > > > }; > > > > > > diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h > > index ab446e0..c56d23e 100644 > > --- a/drivers/misc/lkdtm/lkdtm.h > > +++ b/drivers/misc/lkdtm/lkdtm.h > > @@ -28,6 +28,9 @@ void lkdtm_CORRUPT_USER_DS(void); > > void lkdtm_STACK_GUARD_PAGE_LEADING(void); > > void lkdtm_STACK_GUARD_PAGE_TRAILING(void); > > void lkdtm_UNSET_SMEP(void); > > +#ifdef CONFIG_X86_32 > > +void lkdtm_DOUBLE_FAULT(void); > > +#endif > > Same. If you think I can apply your fixes on top of x86/urgent, so that it goes upstream in a clean fashion? I can also rebase and remove it for the time being - your call! Thanks, Ingo
![]() |