Skip to main content

Segfault

Segfault

プロセスリカバリの実験中にエラーが発生し segfault at 0 ip [useraddr] sp [useraddr] error 6 のようなログが得られたのでどこでエラーが起きているか確認したときのメモ. エラーログは arch/x86/mm/fault.c の show_signal_msg() で出力されていた.

/*
* Print out info about fatal segfaults, if the show_unhandled_signals
* sysctl is set:
*/
static inline void
show_signal_msg(struct pt_regs *regs, unsigned long error_code,
unsigned long address, struct task_struct *tsk)
{
const char *loglvl = task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG;

if (!unhandled_signal(tsk, SIGSEGV))
return;

if (!printk_ratelimit())
return;

printk("%s%s[%d]: segfault at %lx ip %px sp %px error %lx",
loglvl, tsk->comm, task_pid_nr(tsk), address,
(void *)regs->ip, (void *)regs->sp, error_code);

print_vma_addr(KERN_CONT " in ", regs->ip);

printk(KERN_CONT "\n");

show_opcodes(regs, loglvl);
}

show_signal_msg() がどこで呼び出されているかたどっていくと bad_area_nosemaphore() か __bad_area() のどちらかで呼ばれていることがわかった. それぞれの呼び出しは下記のようになっていた.

--> bad_area_nosemaphore()

--> __bad_area_nosemaphore()

--> show_signal_msg()
asm_exc_page_fault()

--> handle_page_fault()

--> do_user_addr_fault()

--> bad_area()
//--> bad_area_access_error()

--> __bad_area()

--> __bad_area_nosemaphore()

--> show_signal_msg()