이번에는 kfree에 대해서 알아봅니다. 이번에도 패치 코드를 하나 작성할게요.
이번에는 kmalloc 함수로 메모리를 할당 후 kfree 함수를 호출해서 메모리를 해제합니다. 그리고 바로 커널 크래시를 유발하죠.
커널 크래시가 발생하면 코어 덤프(vmcore)가 생깁니다. 이 파일을 Trace32로 올려서 메모리 해제 시 어떤 동작을 하는 지 상세히 알아 보려고 하거든요.
우선 할당된 메모리 주소는 0xE7AE1300입니다.
(static u32 *) austin_debug_data = 0xE7AE1300
_____address|_data________|value_____________|symbol
NSD:E7AE1300|6B 6B 6B 6B 0x6B6B6B6B
NSD:E7AE1304|6B 6B 6B 6B 0x6B6B6B6B
NSD:E7AE1308|6B 6B 6B 6B 0x6B6B6B6B
NSD:E7AE130C|6B 6B 6B 6B 0x6B6B6B6B
NSD:E7AE1310|6B 6B 6B 6B 0x6B6B6B6B
NSD:E7AE1314|6B 6B 6B 6B 0x6B6B6B6B
NSD:E7AE1318|6B 6B 6B 6B 0x6B6B6B6B
//...
NSD:E7AE16F8|6B 6B 6B 6B 0x6B6B6B6B
NSD:E7AE16FC|6B 6B 6B A5 0xA56B6B6B
NSD:E7AE1700|BB BB BB BB 0xBBBBBBBB
NSD:E7AE1704|40 0E AE E7 0xE7AE0E40
NSD:E7AE1708|AC 68 43 C0 0xC04368AC \\kernel_bsp_debug_stat_set+0x134
NSD:E7AE170C|F0 EB 14 C0 0xC014EBF0 \\kmem_cache_alloc_trace+0xB8
NSD:E7AE1710|AC 68 43 C0 0xC04368AC \\kernel_bsp_debug_stat_set+0x134
NSD:E7AE1714|10 EF 17 C0 0xC017EF10 \\vmlinux\libfs\simple_attr_write+0xD4
NSD:E7AE1718|60 A7 15 C0 0xC015A760 \\vmlinux\fs/read_write\vfs_write+0xC8
NSD:E7AE171C|EC AB 15 C0 0xC015ABEC \\vmlinux\fs/read_write\sys_write+0x4C
NSD:E7AE1720|00 F3 00 C0 0xC000F300 \\vmlinux\Global\ret_fast_syscall
NSD:E7AE1724|00 00 00 00 0x0
NSD:E7AE1728|00 00 00 00 0x0
NSD:E7AE172C|00 00 00 00 0x0
NSD:E7AE1730|00 00 00 00 0x0
NSD:E7AE1734|00 00 00 00 0x0
NSD:E7AE1738|00 00 00 00 0x0
NSD:E7AE173C|00 00 00 00 0x0
NSD:E7AE1740|00 00 00 00 0x0
NSD:E7AE1744|00 00 00 00 0x0
NSD:E7AE1748|00 00 00 00 0x0
NSD:E7AE174C|07 00 00 00 0x7
NSD:E7AE1750|85 16 00 00 0x1685
NSD:E7AE1754|96 20 00 00 0x2096
NSD:E7AE1758|98 F3 3C C0 0xC03CF398 \\perform_memory_free+0x50
NSD:E7AE175C|40 FA 14 C0 0xC014FA40 \\vmlinux\slub\kfree+0x238
NSD:E7AE1760|98 F3 3C C0 0xC03CF398 \\perform_memory_free+0x50
NSD:E7AE1764|2C C2 F5 C0 0xC0F5C22C \watchdog_kthread+0xF4
NSD:E7AE1768|48 AA 04 C0 0xC004AA48 \\kthread+0xF8
NSD:E7AE176C|D0 F3 00 C0 0xC000F3D0 \\ ret_from_fork+0x14
NSD:E7AE1770|00 00 00 00 0x0
NSD:E7AE1774|00 00 00 00 0x0
NSD:E7AE1778|00 00 00 00 0x0
NSD:E7AE177C|00 00 00 00 0x0
NSD:E7AE1780|00 00 00 00 0x0
NSD:E7AE1784|00 00 00 00 0x0
NSD:E7AE1788|00 00 00 00 0x0
NSD:E7AE178C|00 00 00 00 0x0
NSD:E7AE1790|00 00 00 00 0x0
NSD:E7AE1794|00 00 00 00 0x0
NSD:E7AE1798|00 00 00 00 0x0
NSD:E7AE179C|07 00 00 00 0x7
NSD:E7AE17A0|42 00 00 00 0x42
NSD:E7AE17A4|36 28 00 00 0x2836
NSD:E7AE17A8|5A 5A 5A 5A 0x5A5A5A5A
NSD:E7AE17AC|5A 5A 5A 5A 0x5A5A5A5A
NSD:E7AE17B0|5A 5A 5A 5A 0x5A5A5A5A
NSD:E7AE17B4|5A 5A 5A 5A 0x5A5A5A5A
NSD:E7AE17B8|5A 5A 5A 5A 0x5A5A5A5A
NSD:E7AE17BC|5A 5A 5A 5A 0x5A5A5A5A
kmalloc으로 할당한 메모리를 해제하면 해당 메모리 공간을 0x6b로 채워 넣습니다.
이 헥사 값은 POISON_FREE 매크로로 정의됐는데 이미 해제한 메모리를 뜻합니다.
[include/linux/poison.h]
#define POISON_FREE 0x6b
그럼 이런 헥사 값을 왜 채워 넣을까요? 조금 후 다른 프로세스에서 1024 크기 만큼 메모리 할당을 요청하면 이 메모리 공간을 다음에 할당합니다.
그 때 이 메모리 공간에는 당연히 0x6b 값으로 채워져 있겠죠. 그럼 만약0x6b가 아니라 다른 값이 있으면 어떻게 해석해야 할까요?
리눅스 커널은 이 때 메모리가 오염됐다고 판단하고 커널 크래시를 유발합니다. 메모리 오염이라. 좀 애매한 소리죠.

최근 덧글