Re: BUG: Sporadic crashes with current Linus tree

From: Andy Lutomirski
Date: Thu Sep 14 2017 - 12:45:11 EST


On Thu, Sep 14, 2017 at 9:00 AM, Thomas Gleixner <tglx@xxxxxxxxxxxxx> wrote:
> On Thu, 14 Sep 2017, Andy Lutomirski wrote:
>> On Thu, Sep 14, 2017 at 12:38 AM, Thomas Gleixner <tglx@xxxxxxxxxxxxx> wrote:
>> > Hi!
>> >
>> > I've seen the following crash sporadically with commit 46c1e79fee:
>> >
>> > Have not seen that with 3882a734c19b, though I saw the PCID warnings on
>> > that machine.
>> >
>> > I have no idea how to reproduce so bisecting is pretty much pointless. Any
>> > idea what to do?
>>
>> Does tools/testing/selftests/x86/sigreturn_64 reproduce it?
>
> Will try tomorrow once I figured out how to compile that stuff. Invoking a
> simple make in that directory fails.

What's the error? It works for me.

>
> Built it manually and when I run it tells: stack16 is too high
>
>> Ugh, weird. It kind of looks like current->thread.sp0 == NULL. I
>> have a patch series that changes a bunch of that code in my git tree,
>> but that's definitely not in Linus' tree.
>
> Right. The stupid thing is that the machine did not throw up all day
> neither idle nor loaded. Still the same kernel which barfed tonight several
> times.

This is weird. The crashing process is rsyslogd, which should have
been running for a long time and shouldn't have any strange state. I
wonder if this is some kind of memory corruption. There would have to
be corruption of thread_struct *and* some kind of issue causing IRET
to fail, though.

The attached patch could plausibly give some useful hint.

>
> Thanks,
>
> tglx
>
>
>
>
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 34ea3651362e..fe95ea1da5cd 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -628,6 +628,12 @@ struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s)
container_of(task_pt_regs(current),
struct bad_iret_stack, regs);

+ struct pt_regs *old = container_of((unsigned long *)s->regs.sp, struct pt_regs, ip);
+
+ pr_err("fixup_bad_iret. my sp0 = %lx\n", current->thread.sp0);
+ pr_err("RIP = %lx:%lx RSP = %lx:%lx FLAGS=%lx\n", old->cs, old->ip,
+ old->ss, old->sp, old->flags);
+
/* Copy the IRET target to the new stack. */
memmove(&new_stack->regs.ip, (void *)s->regs.sp, 5*8);