読者です 読者をやめる 読者になる 読者になる

kmemleakデバッグめも2

kernel linux

φ(・・*)ゞ ウーン
git pullしてみたけど結果変わらずなのでめも。
まずはpolicydb_read()の0x100cバイト目のとこでkmem_cache_alloc_trace()が呼ばれるパターンを。

unreferenced object 0xffff8802515906a0 (size 32):
  comm "systemd", pid 1, jiffies 4294678007 (age 115.088s)
  hex dump (first 32 bytes):
    ff 0f 00 00 23 04 00 00 07 00 00 00 00 00 00 00  ....#...........
    f0 b7 58 51 02 88 ff ff 00 00 00 00 00 00 00 00  ..XQ............
  backtrace:
    [<ffffffff815e329b>] kmemleak_alloc+0x5b/0xc0
    [<ffffffff8116dea6>] kmem_cache_alloc_trace+0xb6/0x160
    [<ffffffff81286a3c>] policydb_read+0x100c/0x1260
    [<ffffffff8128b1b9>] security_load_policy+0x59/0x480
    [<ffffffff8127df61>] sel_write_load+0xa1/0x720
    [<ffffffff81183aac>] vfs_write+0xac/0x180
    [<ffffffff81183dda>] sys_write+0x4a/0x90
    [<ffffffff8160c629>] system_call_fastpath+0x16/0x1b
    [<ffffffffffffffff>] 0xffffffffffffffff

objdumpでみると、policydb_read()は0x30a0からスタートなのでこれを基準として0x100cバイト目はというと、

00000000000030a0 <policydb_read>:
    30a0:       55                      push   %rbp
    30a1:       48 89 e5                mov    %rsp,%rbp
    30a4:       41 57                   push   %r15
    30a6:       41 56                   push   %r14
    30a8:       41 55                   push   %r13
 

0x30a0 + 0x100c = 0x40acだからこの辺ですね。

    4097:       0f 84 4e 02 00 00       je     42eb <policydb_read+0x124b>
    409d:       ba 18 00 00 00          mov    $0x18,%edx
    40a2:       be d0 80 00 00          mov    $0x80d0,%esi
    40a7:       e8 00 00 00 00          callq  40ac <policydb_read+0x100c>
    40ac:       48 85 c0                test   %rax,%rax
    40af:       49 89 c5                mov    %rax,%r13
    40b2:       0f 84 20 02 00 00       je     42d8 <policydb_read+0x1238>
    40b8:       48 8b 3d 00 00 00 00    mov    0x0(%rip),%rdi        # 40bf <policydb_read+0x101f>

さて、これがcのコードでどの辺かという話になるのですが、0x40acより前に即値なところがあるのでこれを目印にするとこの2ヶ所になります。

    409d:       ba 18 00 00 00          mov    $0x18,%edx
    40a2:       be d0 80 00 00          mov    $0x80d0,%esi

まずさきにmov $0x80d0,%esiの0x80d0ですが、これはkzalloc()の引数の部分でGFP_KERNEL | __GFP_ZEROの結果が0x80d0でした。
そうすると0x18はkzalloc()のサイズのほうの引数だよねーということで、調べるとsizeof(struct role_trans)が0x18だったので、0x100cのところで呼んでいるメモリ確保の関数は2375行目のところのkzalloc()かな?と予想できたりですが、どうですかねー

	ltr = NULL;
	for (i = 0; i < nel; i++) {
		rc = -ENOMEM;
		tr = kzalloc(sizeof(*tr), GFP_KERNEL);
		if (!tr)