Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

1148
469
422441


slab - kmem_cache 소개 및 slab object(슬랩 오브젝트) Overview [Linux][Kernel] MM


슬랩 메모리 관련해서 자주 쳐다보는 디버깅용 전역 변수를 소개하려고 해요.
kmalloc_caches 인데요.

14 사이즈 어레이로 되어 있는데, "kmalloc-128", "kmalloc-256", ... "kmalloc-8192" 슬랩 인스턴스가 있어요.
  (static struct kmem_cache * [14]) kmalloc_caches = (
    [0x0] = 0x0,
    [0x1] = 0x0,
    [0x2] = 0x0,
    [0x3] = 0x0,
    [0x4] = 0x0,
    [0x5] = 0x0,
    [0x6] = 0x0,
    [0x7] = 0xFFFFFFE579003E00,   // "kmalloc-128"
    [0x8] = 0xFFFFFFE579003D00,   // "kmalloc-256" 
    [0x9] = 0xFFFFFFE579003C00,   // "kmalloc-512" 
    [0x0A] = 0xFFFFFFE579003B00, // "kmalloc-1024"
    [0x0B] = 0xFFFFFFE579003A00, // "kmalloc-2048"
    [0x0C] = 0xFFFFFFE579003900, // "kmalloc-4096"
    [0x0D] = 0xFFFFFFE579003800) // "kmalloc-8192"
.
"kmalloc-128" 슬랩 메모리 정보(struct kmem_cache_cpu *)를 볼께요.
아래 멤버에서 주의깊게 봐야 할 정보가 object_size = 0x80, offset = 0x0 인데요,
당연히 "kmalloc-128" 슬랩 오브젝트 사이즈는 0x80이겠지요.  
  (static struct kmem_cache * [14]) kmalloc_caches = (
    [0x0] = 0x0,
    [0x1] = 0x0,
    [0x2] = 0x0,
    [0x3] = 0x0,
    [0x4] = 0x0,
    [0x5] = 0x0,
    [0x6] = 0x0,
    [0x7] = 0xFFFFFFE579003E00 -> (
      (struct kmem_cache_cpu *) cpu_slab = 0xFFFFFF9F9B234C00,
      (long unsigned int) flags = 0x40000000,
      (long unsigned int) min_partial = 0x5,
      (int) size = 0x80,
      (int) object_size = 0x80,
      (int) offset = 0x0,
      (int) cpu_partial = 0x1E,
      (struct kmem_cache_order_objects) oo = ((long unsigned int) x = 0x20),
      (struct kmem_cache_order_objects) max = ((long unsigned int) x = 0x20),
      (struct kmem_cache_order_objects) min = ((long unsigned int) x = 0x20),
      (gfp_t) allocflags = 0x0,
      (int) refcount = 0x8,
      (void (*)()) ctor = 0x0,
      (int) inuse = 0x80,
      (int) align = 0x80,
      (int) reserved = 0x0,
      (char *) name = 0xFFFFFF9F9AE0490E -> "kmalloc-128",
      (struct list_head) list = ((struct list_head *) next = 0xFFFFFFE579003F68, (struct list_head *) prev =
      (int) red_left_pad = 0x0,
      (struct kobject) kobj = ((char *) name = 0xFFFFFFE575E6DC80 -> ":t-0000128", (struct list_head) entry
      (struct kmem_cache_node * [1]) node = ([0x0] = 0xFFFFFFE579000F80)),
    [0x8] = 0xFFFFFFE579003D00,
.
CPU0의 percpu slab cache 정보를 확인해 볼께요.
*참고로, 아래 0xFFFFFF9F9B234C00 주소는 위에서 확인된 "(struct kmem_cache_cpu *) cpu_slab = 0xFFFFFF9F9B234C00"이랍니다. 

그럼 할당가능한 "kmalloc-128" 슬랩 오브젝트를 확인해볼까요?
  (struct kmem_cache_cpu *) (struct kmem_cache_cpu *)(0xFFFFFF9F9B234C00+__per_cpu_offset[0]) = 0xFF
    (void * *) freelist = 0xFFFFFFE4D882CC80,
    (long unsigned int) tid = 270496 = 0x000420A0,
    (struct page *) page = 0xFFFFFFBE53620B00,
    (struct page *) partial = 0xFFFFFFBE553866C0)
.
.
_____________address|_data____________________|value____________ 
NSD:FFFFFFE4D882CC80| 00 CC 82 D8 E4 FF FF FF  0xFFFFFFE4D882CC00
NSD:FFFFFFE4D882CC88| 00 00 00 00 00 00 00 00  0x0

_____________address|_data____________________|value____________ 
NSD:FFFFFFE4D882CC00| 00 CD 82 D8 E4 FF FF FF  0xFFFFFFE4D882CD00
NSD:FFFFFFE4D882CC08| 08 CC 82 D8 E4 FF FF FF  0xFFFFFFE4D882CC08

_____________address|_data____________________|value____________ 
NSD:FFFFFFE4D882CD00| 00 CE 82 D8 E4 FF FF FF  0xFFFFFFE4D882CE00
NSD:FFFFFFE4D882CD08| 00 00 00 00 00 00 00 00  0x0

_____________address|_data____________________|value____________ 
NSD:FFFFFFE4D882CE00| 80 CD 82 D8 E4 FF FF FF  0xFFFFFFE4D882CD80
NSD:FFFFFFE4D882CE08| 00 00 00 00 00 00 00 00  0x0
_____________address|_data____________________|value____________ 
NSD:FFFFFFE4D882CD80| 00 CF 82 D8 E4 FF FF FF  0xFFFFFFE4D882CF00
NSD:FFFFFFE4D882CD88| 88 CD 82 D8 E4 FF FF FF  0xFFFFFFE4D882CD88

_____________address|_data____________________|value____________ 
NSD:FFFFFFE4D882CF00| 80 CE 82 D8 E4 FF FF FF  0xFFFFFFE4D882CE80
NSD:FFFFFFE4D882CF08| 00 00 00 00 00 00 00 00  0x0

_____________address|_data____________________|value____________ 
NSD:FFFFFFE4D882CE80| 00 CB 82 D8 E4 FF FF FF  0xFFFFFFE4D882CB00
NSD:FFFFFFE4D882CE88| 88 CE 82 D8 E4 FF FF FF  0xFFFFFFE4D882CE88

______________address|_data____________________|value___________ 
NSD:FFFFFFE4D882CB00| 80 CF 82 D8 E4 FF FF FF  0xFFFFFFE4D882CF80
NSD:FFFFFFE4D882CB08| 00 00 00 00 00 00 00 00  0x0

_____________address|_data____________________|value____________ 
NSD:FFFFFFE4D882CF80| 00 00 00 00 00 00 00 00  0x0
NSD:FFFFFFE4D882CF88| 88 CF 82 D8 E4 FF FF FF  0xFFFFFFE4D882CF88
.
슬랩 오브젝트가 아래 순서로 줄 서 있네요.
0xFFFFFFE4D882CC00 -> 0xFFFFFFE4D882CD00 -> 0xFFFFFFE4D882CE00 -> 0xFFFFFFE4D882CD80  -> 0xFFFFFFE4D882CF00 -> 0xFFFFFFE4D882CE80 -> 0xFFFFFFE4D882CB00 -> 0xFFFFFFE4D882CF80

위와 같이 검색한 원리는 이 슬랩 오브젝트의 offset = 0x0가 이라서 가능한 거에요.
offset이 있으면 반드시 더해서 다음 슬랩 오브젝트의 위치를 계산해야 되요.

슬랩 메모리 할당 원리나 데이터 구조체는 최고급 리눅스 커널 개발자가 되려는 분은 반드시 알아야 되요.
슬랩 메모리가 깨져서 커널 크래시가 날 경우 근본 원인을 잡기 매우 어려운 경우가 많거든요.

이럴 때 나서서 어려운 문제를 해결하면 아우라를 풍길 수 있기 때문이죠.

상세한 slab memory 코드 리뷰와 slab memory corruption 디버깅 방법에 대해서는 다음에 업데이트할 예정이에요.



# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2





핑백

덧글

댓글 입력 영역