All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andy Lutomirski <luto@kernel.org>
To: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>, X86 ML <x86@kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	live-patching@vger.kernel.org,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Jiri Slaby <jslaby@suse.cz>, Ingo Molnar <mingo@kernel.org>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Mike Galbraith <efault@gmx.de>
Subject: Re: [PATCH v2 6/8] x86/entry: add unwind hint annotations
Date: Thu, 29 Jun 2017 22:05:14 -0700	[thread overview]
Message-ID: <CALCETrWBDOgfuX+uSukZ+_PHT4_j87LXY-DXPvCZ_KEXcnkWwg@mail.gmail.com> (raw)
In-Reply-To: <20170630021249.cqkszxaqtwakmzpg@treble>

On Thu, Jun 29, 2017 at 7:12 PM, Josh Poimboeuf <jpoimboe@redhat.com> wrote:
> On Thu, Jun 29, 2017 at 03:59:04PM -0700, Andy Lutomirski wrote:
>> >
>> > Sorry, I didn't explain it very well.  Undwarf can find the regs pointer
>> > in rdi, it just doesn't trust its value.
>> >
>> > See the stack_info.next_sp field, which is set in in_irq_stack():
>> >
>> >    /*
>> >     * The next stack pointer is the first thing pushed by the entry code
>> >     * after switching to the irq stack.
>> >     */
>> >    info->next_sp = (unsigned long *)*(end - 1);
>> >
>> > It's a safety mechanism.  The unwinder needs the last word of the irq
>> > stack page to point to the previous stack.  That way it can double check
>> > that the stack pointer it calculates is within the bounds of either the
>> > current stack or the previous stack.
>> >
>> > In the above code, the previous stack pointer (or next stack pointer,
>> > depending on your perspective) hasn't been set up before it switches
>> > stacks.  So the unwinder reads an uninitialized value into
>> > info->next_sp, and compares that with the regs pointer, and then stops
>> > the unwind because it thinks it went off into the weeds.
>> >
>>
>> That should be manageable, though, I think.  With my patch applied
>> (and maybe even without it), the only exception to that rule is if
>> regs->sp points just above the top of the IRQ stack and the next
>> instruction is push reg.  In that case, the reg is exactly as
>> trustworthy as the normal rule.*  Can you teach the unwinding code
>> that this is okay?
>>
>> * If an NMI hits right there, then it relies on unwinding out of the
>> NMI correctly.  But the usual checks that the target stack is a valid
>> stack should prevent us from going off into the weeds regardless.
>
> But that would remove a safeguard against the undwarf data being
> corrupt.  Sure, it would only affect the rare case where the stack
> pointer is at the top of the IRQ stack, but still...
>
> Also, the frame pointer and guess unwinders have the same issue, and
> this solution wouldn't work for them.
>
> And, worst of all, the oops stack dumping code in show_trace_log_lvl()
> also has this issue .  It relies on those previous stack pointers.  And
> it's separated from the unwinder logic by design, so it can't ask the
> unwinder where the next stack is.

Ugh.

I feel like we had this debate before, and I thought it was rather
silly that the unwinder cared.  After all, we already have separate
safety mechanisms to make sure that the unwinder never wanders off of
the valid stacks and that it never touches any given stack more than
once.  But it is indeed useful for the oops unwinder, so c'est la vie.

That being said, I bet we could get away with this (sorry for immense
whitespace damage):

.macro ENTER_IRQ_STACK old_rsp scratch_reg
  DEBUG_ENTRY_ASSERT_IRQS_OFF
  movq %rsp, \old_rsp
  incl PER_CPU_VAR(irq_count)
  jnz .Lrecurse_irq_stack_\@

   /*
   * Right now, we just incremented irq_count to zero, so we've
   * claimed the IRQ stack but we haven't switched to it yet.
   * Anything that can interrupt us here without using IST
   * must be *extremely* careful to limit its stack usage.
   *
   * We write old_rsp to the IRQ stack before switching to
   * %rsp for the benefit of the OOPS unwinder.
   */
   movq PER_CPU_VAR(irq_stack_ptr), \scratch_reg
   movq \old_rsp, -8(\scratch_reg)
   leaq -8(\old_rsp), %rsp
   jmp .Lout_\@

   .Lrecurse_irq_stack_\@:
   pushq \old_rsp

   .Lout_\@:
.endm

After all, it looks like all the users have a scratch reg available.

Hmm.  There's another option that might be considerably nicer, though:
put the IRQ stack at a known (at link time) position *in percpu
space*.  (Presumably it already is -- I haven't checked.)  Then we do:

.macro ENTER_IRQ_STACK old_rsp
    DEBUG_ENTRY_ASSERT_IRQS_OFF
    movq    %rsp, \old_rsp
    incl    PER_CPU_VAR(irq_count)

    /*
     * Right now, if we just incremented irq_count to zero, we've
     * claimed the IRQ stack but we haven't switched to it yet.
     * Anything that can interrupt us here without using IST
     * must be *extremely* careful to limit its stack usage.
     */
    jnz .Lpush_old_rsp_\@
    movq    \old_rsp, PER_CPU_VAR(top_word_in_irq_stack)
    movq    PER_CPU_VAR(irq_stack_ptr), %rsp
    .Lpush_old_rsp_\@:
    pushq    \old_rsp
.endm

This pushes the old pointer twice, but that's easy enough to fix if we
really cared.  I think I like this variant better.  What do you think?

--Andy

  reply	other threads:[~2017-06-30  5:05 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-28 15:11 [PATCH v2 0/8] x86: undwarf unwinder Josh Poimboeuf
2017-06-28 15:11 ` [PATCH v2 1/8] objtool: move checking code to check.c Josh Poimboeuf
2017-06-30 13:12   ` [tip:core/objtool] objtool: Move " tip-bot for Josh Poimboeuf
2017-06-28 15:11 ` [PATCH v2 2/8] objtool, x86: add several functions and files to the objtool whitelist Josh Poimboeuf
2017-06-30 13:12   ` [tip:core/objtool] objtool, x86: Add " tip-bot for Josh Poimboeuf
2017-06-28 15:11 ` [PATCH v2 3/8] objtool: stack validation 2.0 Josh Poimboeuf
2017-06-30  8:32   ` Ingo Molnar
2017-06-30 13:23     ` Josh Poimboeuf
2017-06-30 13:26       ` Josh Poimboeuf
2017-06-30 14:09     ` [PATCH] objtool: silence warnings for functions which use iret Josh Poimboeuf
2017-06-30 17:49       ` [tip:core/objtool] objtool: Silence warnings for functions which use IRET tip-bot for Josh Poimboeuf
2017-06-30 13:13   ` [tip:core/objtool] objtool: Implement stack validation 2.0 tip-bot for Josh Poimboeuf
2017-06-28 15:11 ` [PATCH v2 4/8] objtool: add undwarf debuginfo generation Josh Poimboeuf
2017-06-29  7:14   ` Ingo Molnar
2017-06-29 13:40     ` Josh Poimboeuf
2017-06-29  7:25   ` Ingo Molnar
2017-06-29 14:04     ` Josh Poimboeuf
2017-06-29 14:46       ` Ingo Molnar
2017-06-29 15:06         ` Josh Poimboeuf
2017-07-06 20:36           ` Josh Poimboeuf
2017-07-07  9:44             ` Ingo Molnar
2017-07-11  2:58               ` Josh Poimboeuf
2017-07-11  8:40                 ` Ingo Molnar
2017-06-28 15:11 ` [PATCH v2 5/8] objtool, x86: add facility for asm code to provide unwind hints Josh Poimboeuf
2017-06-28 15:11 ` [PATCH v2 6/8] x86/entry: add unwind hint annotations Josh Poimboeuf
2017-06-29 17:53   ` Josh Poimboeuf
2017-06-29 18:50     ` Andy Lutomirski
2017-06-29 19:05       ` Josh Poimboeuf
2017-06-29 21:09         ` Andy Lutomirski
2017-06-29 21:41           ` Josh Poimboeuf
2017-06-29 22:59             ` Andy Lutomirski
2017-06-30  2:12               ` Josh Poimboeuf
2017-06-30  5:05                 ` Andy Lutomirski [this message]
2017-06-30  5:41                   ` Andy Lutomirski
2017-06-30 13:11                     ` Josh Poimboeuf
2017-06-30 15:44                       ` Andy Lutomirski
2017-06-30 15:55                         ` Josh Poimboeuf
2017-06-30 15:56                           ` Andy Lutomirski
2017-06-30 16:16                             ` Josh Poimboeuf
2017-06-28 15:11 ` [PATCH v2 7/8] x86/asm: add unwind hint annotations to sync_core() Josh Poimboeuf
2017-06-28 15:11 ` [PATCH v2 8/8] x86/unwind: add undwarf unwinder Josh Poimboeuf
2017-06-29  7:55 ` [PATCH v2 0/8] x86: " Ingo Molnar
2017-06-29 14:12   ` Josh Poimboeuf
2017-06-29 19:13     ` Josh Poimboeuf

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=CALCETrWBDOgfuX+uSukZ+_PHT4_j87LXY-DXPvCZ_KEXcnkWwg@mail.gmail.com \
    --to=luto@kernel.org \
    --cc=efault@gmx.de \
    --cc=hpa@zytor.com \
    --cc=jpoimboe@redhat.com \
    --cc=jslaby@suse.cz \
    --cc=linux-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=torvalds@linux-foundation.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.