/* Called from get_stack_info_noinstr - so must be noinstr too */ bool noinstr in_entry_stack(unsignedlong *stack, struct stack_info *info)
{ struct entry_stack *ss = cpu_entry_stack(smp_processor_id());
void *begin = ss; void *end = ss + 1;
if ((void *)stack < begin || (void *)stack >= end) returnfalse;
/* The user space code from other tasks cannot be accessed. */ if (regs != task_pt_regs(current)) return -EPERM;
/* * Even if named copy_from_user_nmi() this can be invoked from * other contexts and will not try to resolve a pagefault, which is * the correct thing to do here as this code can be called from any * context.
*/ return copy_from_user_nmi(buf, (void __user *)src, nbytes);
}
/* * There are a couple of reasons for the 2/3rd prologue, courtesy of Linus: * * In case where we don't have the exact kernel image (which, if we did, we can * simply disassemble and navigate to the RIP), the purpose of the bigger * prologue is to have more context and to be able to correlate the code from * the different toolchains better. * * In addition, it helps in recreating the register allocation of the failing * kernel and thus make sense of the register dump. * * What is more, the additional complication of a variable length insn arch like * x86 warrants having longer byte sequence before rIP so that the disassembler * can "sync" up properly and find instruction boundaries when decoding the * opcode bytes. * * Thus, the 2/3rds prologue and 64 byte OPCODE_BUFSIZE is just a random * guesstimate in attempt to achieve all of the above.
*/ void show_opcodes(struct pt_regs *regs, constchar *loglvl)
{ #define PROLOGUE_SIZE 42 #define EPILOGUE_SIZE 21 #define OPCODE_BUFSIZE (PROLOGUE_SIZE + 1 + EPILOGUE_SIZE)
u8 opcodes[OPCODE_BUFSIZE]; unsignedlong prologue = regs->ip - PROLOGUE_SIZE;
switch (copy_code(regs, opcodes, prologue, sizeof(opcodes))) { case 0:
printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %"
__stringify(EPILOGUE_SIZE) "ph\n", loglvl, opcodes,
opcodes[PROLOGUE_SIZE], opcodes + PROLOGUE_SIZE + 1); break; case -EPERM: /* No access to the user space stack of other tasks. Ignore. */ break; default:
printk("%sCode: Unable to access opcode bytes at 0x%lx.\n",
loglvl, prologue); break;
}
}
staticvoid show_regs_if_on_stack(struct stack_info *info, struct pt_regs *regs, bool partial, constchar *log_lvl)
{ /* * These on_stack() checks aren't strictly necessary: the unwind code * has already validated the 'regs' pointer. The checks are done for * ordering reasons: if the registers are on the next stack, we don't * want to print them out yet. Otherwise they'll be shown as part of * the wrong stack. Later, when show_trace_log_lvl() switches to the * next stack, this function will be called again with the same regs so * they can be printed in the right context.
*/ if (!partial && on_stack(info, regs, sizeof(*regs))) {
__show_regs(regs, SHOW_REGS_SHORT, log_lvl);
} elseif (partial && on_stack(info, (void *)regs + IRET_FRAME_OFFSET,
IRET_FRAME_SIZE)) { /* * When an interrupt or exception occurs in entry code, the * full pt_regs might not have been saved yet. In that case * just print the iret frame.
*/
show_iret_regs(regs, log_lvl);
}
}
/* * This function reads pointers from the stack and dereferences them. The * pointers may not have their KMSAN shadow set up properly, which may result * in false positive reports. Disable instrumentation to avoid those.
*/
__no_kmsan_checks staticvoid show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, unsignedlong *stack, constchar *log_lvl)
{ struct unwind_state state; struct stack_info stack_info = {0}; unsignedlong visit_mask = 0; int graph_idx = 0; bool partial = false;
/* * Iterate through the stacks, starting with the current stack pointer. * Each stack has a pointer to the next one. * * x86-64 can have several stacks: * - task stack * - interrupt stack * - HW exception stacks (double fault, nmi, debug, mce) * - entry stack * * x86-32 can have up to four stacks: * - task stack * - softirq stack * - hardirq stack * - entry stack
*/ for (; stack; stack = stack_info.next_sp) { constchar *stack_name;
stack = PTR_ALIGN(stack, sizeof(long));
if (get_stack_info(stack, task, &stack_info, &visit_mask)) { /* * We weren't on a valid stack. It's possible that * we overflowed a valid stack into a guard page. * See if the next page up is valid so that we can * generate some kind of backtrace if this happens.
*/
stack = (unsignedlong *)PAGE_ALIGN((unsignedlong)stack); if (get_stack_info(stack, task, &stack_info, &visit_mask)) break;
}
stack_name = stack_type_name(stack_info.type); if (stack_name)
printk("%s <%s>\n", log_lvl, stack_name);
if (regs)
show_regs_if_on_stack(&stack_info, regs, partial, log_lvl);
/* * Scan the stack, printing any text addresses we find. At the * same time, follow proper stack frames with the unwinder. * * Addresses found during the scan which are not reported by * the unwinder are considered to be additional clues which are * sometimes useful for debugging and are prefixed with '?'. * This also serves as a failsafe option in case the unwinder * goes off in the weeds.
*/ for (; stack < stack_info.end; stack++) { unsignedlong real_addr; int reliable = 0; unsignedlong addr = READ_ONCE_NOCHECK(*stack); unsignedlong *ret_addr_p =
unwind_get_return_address_ptr(&state);
if (!__kernel_text_address(addr)) continue;
/* * Don't print regs->ip again if it was already printed * by show_regs_if_on_stack().
*/ if (regs && stack == ®s->ip) goto next;
if (stack == ret_addr_p)
reliable = 1;
/* * When function graph tracing is enabled for a * function, its return address on the stack is * replaced with the address of an ftrace handler * (return_to_handler). In that case, before printing * the "real" address, we want to print the handler * address as an "unreliable" hint that function graph * tracing was involved.
*/
real_addr = ftrace_graph_ret_addr(task, &graph_idx,
addr, stack); if (real_addr != addr)
printk_stack_address(addr, 0, log_lvl);
printk_stack_address(real_addr, reliable, log_lvl);
if (!reliable) continue;
next: /* * Get the next frame from the unwinder. No need to * check for an error: if anything goes wrong, the rest * of the addresses will just be printed as unreliable.
*/
unwind_next_frame(&state);
/* if the frame has entry regs, print them */
regs = unwind_get_entry_regs(&state, &partial); if (regs)
show_regs_if_on_stack(&stack_info, regs, partial, log_lvl);
}
if (stack_name)
printk("%s %s>\n", log_lvl, stack_name);
}
}
/* * Stack frames below this one aren't interesting. Don't show them * if we're printing for %current.
*/ if (!sp && task == current)
sp = get_stack_pointer(current, NULL);
/* Executive summary in case the oops scrolled away */
__show_regs(&exec_summary_regs, SHOW_REGS_ALL, KERN_DEFAULT);
if (!signr) return; if (in_interrupt())
panic("Fatal exception in interrupt"); if (panic_on_oops)
panic("Fatal exception");
/* * We're not going to return, but we might be on an IST stack or * have very little stack space left. Rewind the stack and kill * the task. * Before we rewind the stack, we have to tell KASAN that we're going to * reuse the task stack and that existing poisons are invalid.
*/
kasan_unpoison_task_stack(current);
rewind_stack_and_make_dead(signr);
}
NOKPROBE_SYMBOL(oops_end);
staticvoid __die_header(constchar *str, struct pt_regs *regs, long err)
{ /* Save the regs of the first oops for the executive summary later. */ if (!die_counter)
exec_summary_regs = *regs;
int __die(constchar *str, struct pt_regs *regs, long err)
{
__die_header(str, regs, err); return __die_body(str, regs, err);
}
NOKPROBE_SYMBOL(__die);
/* * This is gone through when something in the kernel has done something bad * and is about to be terminated:
*/ void die(constchar *str, struct pt_regs *regs, long err)
{ unsignedlong flags = oops_begin(); int sig = SIGSEGV;
if (__die(str, regs, err))
sig = 0;
oops_end(flags, regs, sig);
}
void die_addr(constchar *str, struct pt_regs *regs, long err, long gp_addr)
{ unsignedlong flags = oops_begin(); int sig = SIGSEGV;
__die_header(str, regs, err); if (gp_addr)
kasan_non_canonical_hook(gp_addr); if (__die_body(str, regs, err))
sig = 0;
oops_end(flags, regs, sig);
}
/* * When in-kernel, we also print out the stack at the time of the fault..
*/ if (!user_mode(regs))
show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.