カーネル関数
からの SIGSEGV の生成はarch/x86/mm/fault.c
次のとおりです: http://lxr.missinglinkelectronics.com/linux+v3.12/arch/x86/mm/fault.c#L760__bad_area_nosemaphore()
760 tsk->thread.cr2 = address;
761 tsk->thread.error_code = error_code;
762 tsk->thread.trap_nr = X86_TRAP_PF;
763
764 force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0);
error_code
フィールドがあり、その値も定義されていarch/x86/mm/fault.c
ます:
http://lxr.missinglinkelectronics.com/linux+v3.12/arch/x86/mm/fault.c#L23
23/*
24 * Page fault error code bits:
25 *
26 * bit 0 == 0: no page found 1: protection fault
27 * bit 1 == 0: read access 1: write access
28 * bit 2 == 0: kernel-mode access 1: user-mode access
29 * bit 3 == 1: use of reserved bit detected
30 * bit 4 == 1: fault was an instruction fetch
31 */
32enum x86_pf_error_code {
33
34 PF_PROT = 1 << 0,
35 PF_WRITE = 1 << 1,
36 PF_USER = 1 << 2,
37 PF_RSVD = 1 << 3,
38 PF_INSTR = 1 << 4,
39};
したがって、アクセス タイプに関する正確な情報は次の場所に保存されthread_struct.error_code
ます。
私が見るように、error_code
フィールドは構造体にエクスポートされません( http://man7.org/linux/man-pages/man2/sigaction.2.htmlsiginfo_t
で定義されてい
ます..si_signoを検索してください)。
だからあなたはできる
- カーネルをハックしてエクスポートします(または、既にエクスポートされているかどうかを確認します
tsk->thread.error_code
。たとえば、.ptrace
- メモリ アドレスを取得し、読み取り
/proc/self/maps
、解析し、ページのアクセス ビットをチェックします。ページが存在し、読み取り専用である場合、考えられる唯一の障害は書き込みによるものであり、ページが存在しない場合、両方の種類のアクセスが可能であり、もし... 書き込み専用ページがないはずです。
- また、失敗した命令のアドレスを見つけて、それを読み取って逆アセンブルすることもできます。