クラッシュ発生時の記録
crash> bt
PID: 0 TASK: ffff88033213aee0 CPU: 4 COMMAND: "kworker/0:1"
#0 [ffff880001b03900] machine_kexec at ffffffff81021420
#1 [ffff880001b03980] crash_kexec at ffffffff8107e786
#2 [ffff880001b03a50] oops_end at ffffffff813d2fd3
#3 [ffff880001b03a80] die at ffffffff81006861
#4 [ffff880001b03ab0] do_general_protection at ffffffff813d2bb0
#5 [ffff880001b03b00] general_protection at ffffffff813d21f5
[exception RIP: hidraw_report_event+170]
RIP: ffffffff8130cb3b RSP: ffff880001b03bb8 RFLAGS: 00010096
RAX: 0000000000000002 RBX: dead0000000ffce8 RCX: 0000000000000000
RDX: 0000000000020001 RSI: 000000000000001d RDI: ffff880330efac08
RBP: ffff880001b03bf8 R8: ffff880001b0fd68 R9: 0000000000000007
R10: 0000000000000000 R11: 0000000000000000 R12: ffff88032ab107e0
R13: 0000000000000007 R14: ffff88032ab10818 R15: ffff880037853000
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
#6 [ffff880001b03c00] hid_report_raw_event at ffffffff813079f0
#7 [ffff880001b03ca0] hid_input_report at ffffffff81307f30
[exception RIP: hidraw_report_event+170]で不具合発生したことが示されている。
逆アセンブルを行い、PANICポイントの命令列を得ておく
crash> dis hidraw_report_event
0xffffffff8130ca91 : push %rbp
0xffffffff8130ca92 : mov %rsp,%rbp
0xffffffff8130ca95 : push %r15
0xffffffff8130ca97 : push %r14
0xffffffff8130ca99 : push %r13
0xffffffff8130ca9b : push %r12
0xffffffff8130ca9d : push %rbx
0xffffffff8130ca9e : sub $0x18,%rsp
0xffffffff8130caa2 : nopl 0x0(%rax,%rax,1)
0xffffffff8130caa7 : mov 0x1a10(%rdi),%r12
0xffffffff8130caae : movslq %edx,%rax
0xffffffff8130cab1 : mov %rsi,%r15
0xffffffff8130cab4 : mov %edx,%r13d
0xffffffff8130cab7 : mov 0x38(%r12),%rbx
0xffffffff8130cabc : lea 0x38(%r12),%r14
0xffffffff8130cac1 : mov %rax,-0x40(%rbp)
0xffffffff8130cac5 : sub $0x418,%rbx
0xffffffff8130cacc : jmp 0xffffffff8130cb3b
0xffffffff8130cace : movslq 0x400(%rbx),%rax
0xffffffff8130cad5 : mov -0x40(%rbp),%rsi
0xffffffff8130cad9 : mov $0x20,%edx
0xffffffff8130cade : mov %r15,%rdi
0xffffffff8130cae1 : mov %rax,-0x38(%rbp)
0xffffffff8130cae5 : callq 0xffffffff810d4333
0xffffffff8130caea : mov -0x38(%rbp),%rdx
0xffffffff8130caee : lea 0x408(%rbx),%rdi
0xffffffff8130caf5 : mov $0x1d,%esi
0xffffffff8130cafa : shl $0x4,%rdx
0xffffffff8130cafe : mov %rax,(%rdx,%rbx,1)
0xffffffff8130cb02 : movslq 0x400(%rbx),%rax
0xffffffff8130cb09 : mov $0x20001,%edx
0xffffffff8130cb0e : shl $0x4,%rax
0xffffffff8130cb12 : mov %r13d,0x8(%rax,%rbx,1)
0xffffffff8130cb17 : mov 0x400(%rbx),%eax
0xffffffff8130cb1d : inc %eax
0xffffffff8130cb1f : and $0x3f,%eax
0xffffffff8130cb22 : mov %eax,0x400(%rbx)
0xffffffff8130cb28 : callq 0xffffffff81115da0
0xffffffff8130cb2d : mov 0x418(%rbx),%rbx
0xffffffff8130cb34 : sub $0x418,%rbx
0xffffffff8130cb3b : mov 0x418(%rbx),%rax
0xffffffff8130cb42 : prefetcht0 (%rax)
0xffffffff8130cb45 : lea 0x418(%rbx),%rax
0xffffffff8130cb4c : cmp %rax,%r14
0xffffffff8130cb4f : jne 0xffffffff8130cace
0xffffffff8130cb55 : lea 0x10(%r12),%rdi
0xffffffff8130cb5a : xor %ecx,%ecx
0xffffffff8130cb5c : mov $0x1,%edx
0xffffffff8130cb61 : mov $0x1,%esi
0xffffffff8130cb66 : callq 0xffffffff81035f3f <__wake_up>
0xffffffff8130cb6b : add $0x18,%rsp
0xffffffff8130cb6f : pop %rbx
0xffffffff8130cb70 : pop %r12
0xffffffff8130cb72 : pop %r13
0xffffffff8130cb74 : pop %r14
0xffffffff8130cb76 : pop %r15
0xffffffff8130cb78 : leaveq
0xffffffff8130cb79 : retq
0xffffffff8130cb7a : nop
0xffffffff8130cb7b : nop
crash>
: mov 0x418(%rbx),%rax と、上記レジスタの値からRBX が範囲外を指していることがわかる。
上記のように、ソースコードを特定したら、下記手順でdrivers/hid/hidraw.cのアセンブラ出力を生成する。
.loc 1の横の番号がソースコード行である。
# cd /usr/src/linux-2.6.36.4RedHawk6.0.2
# export O=-g; make drivers/hid/hidraw.s
CHK include/linux/version.h
CHK include/generated/utsrelease.h
CALL scripts/checksyscalls.sh
make[1]: `drivers/hid/hidraw.s' is up to date.
# cat drivers/hid/hidraw.s
.globl hidraw_report_event
.type hidraw_report_event, @function
hidraw_report_event:
.LFB1266:
.loc 1 346 0
.cfi_startproc
.LVL192:
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
pushq %r15 #
pushq %r14 #
pushq %r13 #
pushq %r12 #
pushq %rbx #
subq $24, %rsp #,
call mcount
.loc 1 346 0
.loc 1 347 0
movq 6672(%rdi), %r12 # .hidraw, dev
.cfi_offset 3, -56
.cfi_offset 12, -48
.cfi_offset 13, -40
.cfi_offset 14, -32
.cfi_offset 15, -24
.LVL193:
.loc 1 351 0
movslq %edx, %rax # len,
.loc 1 346 0
movq %rsi, %r15 # data, data
movl %edx, %r13d # len, len
.LBB661:
.loc 1 350 0
movq 56(%r12), %rbx # .list.next, .list.next
.LBE661:
leaq 56(%r12), %r14 #, D.26980
.loc 1 351 0
movq %rax, -64(%rbp) #, %sfp
.LBB662:
.loc 1 350 0
subq $1048, %rbx #, list
.LVL194:
.LBE662:
jmp .L114 #
.LVL195:
.L115:
.loc 1 351 0
movslq 1024(%rbx), %rax # .head,
movq -64(%rbp), %rsi # %sfp,
movl $32, %edx #,
movq %r15, %rdi # data,
movq %rax, -56(%rbp) #, %sfp
call kmemdup #
movq -56(%rbp), %rdx # %sfp, tmp70
.loc 1 354 0
leaq 1032(%rbx), %rdi #, tmp77
movl $29, %esi #,
.loc 1 351 0
salq $4, %rdx #, tmp70
movq %rax, (%rdx,%rbx) # D.26972, .value
.loc 1 352 0
movslq 1024(%rbx), %rax # .head, tmp73
.loc 1 354 0
movl $131073, %edx #,
.loc 1 352 0
salq $4, %rax #, tmp73
movl %r13d, 8(%rax,%rbx) # len, .len
.loc 1 353 0
movl 1024(%rbx), %eax # .head, .head
incl %eax # tmp76
andl $63, %eax #, tmp76
movl %eax, 1024(%rbx) # tmp76, .head
.loc 1 354 0
call kill_fasync #
.LVL196:
.LBB663:
.loc 1 350 0
movq 1048(%rbx), %rbx # .node.next, __mptr.462 /* ここから357 行の前までが350 行の list_for_each_entry(list, &dev->list, node) が展開されたもの */
.LVL197:
subq $1048, %rbx #, list
.LVL198:
.L114:
.LBE663:
movq 1048(%rbx), %rax # .node.next, .node.next /* 1048 は0x418 */
prefetcht0 (%rax) # .node.next
leaq 1048(%rbx), %rax #, tmp79
cmpq %rax, %r14 # tmp79, D.26980
jne .L115 #,
.loc 1 357 0 /* 357 行*/
leaq 16(%r12), %rdi #, tmp80
xorl %ecx, %ecx #
movl $1, %edx #,
movl $1, %esi #,
call __wake_up #
.loc 1 358 0
addq $24, %rsp #,
popq %rbx #
.cfi_restore 3
.LVL199:
popq %r12 #
.cfi_restore 12
.LVL200:
popq %r13 #
.cfi_restore 13
.LVL201:
popq %r14 #
.cfi_restore 14
.LVL202:
popq %r15 #
.cfi_restore 15
.LVL203:
leave
.cfi_restore 6
.cfi_def_cfa 7, 8
ret