On Thu, Aug 04, 2016 at 05:22:32PM -0500, Josh Poimboeuf wrote: > With frame pointers, when a task is interrupted, its stack is no longer > completely reliable because the function could have been interrupted > before it had a chance to save the previous frame pointer on the stack. > So the caller of the interrupted function could get skipped by a stack > trace. > > This is problematic for live patching, which needs to know whether a > stack trace of a sleeping task can be relied upon. There's currently no > way to detect if a sleeping task was interrupted by a page fault > exception or preemption before it went to sleep. > > Another issue is that when dumping the stack of an interrupted task, the > unwinder has no way of knowing where the saved pt_regs registers are, so > it can't print them. > > This solves those issues by encoding the pt_regs pointer in the frame > pointer on entry from an interrupt or an exception. The frame pointer > unwinder is also updated to decode it. > > Suggested-by: Andy Lutomirski <[email protected]> > Signed-off-by: Josh Poimboeuf <[email protected]>
When doing some testing on x86_32, I realized there's a flaw here in the unwinder's pt_regs detection, when an interrupt hits when we're already in the entry code. For example, a page fault can be interrupted by an irq, after the page fault entry code encoded the frame pointer, but before it had a chance to call into the C handler. In that case, regs->bp itself is encoded, and the current "pt_regs aren't real frames" design falls apart because there can actually be more than one set of pt_regs per "frame". So the unwinder gets confused and stops walking the stack too early. So really the unwinder needs to consider each pt_regs as a frame in and of itself. Which of course Andy already suggested before, but I stupidly shot it down. Working on that for v3. -- Josh

