[ptmalloc2] _int_free

dandb3·2023년 7월 13일
0

pwnable

목록 보기
14/22

prototype & 기본 변수들

prototype

  • size : chunk의 크기

mp_ 구조체

mp_

  • malloc과 관련된 여러 상수값들이 저장되어 있다.

tcache

tcache_entry & tcache_perthread_struct

tcache_entry & tcache_perthread_struct

  • tcache_entry

    • tcache_entry는 chunk의 data가 쓰이는 영역부터 쓰이게 된다.
    • next : tcache_bin의 다음 chunk의 tcache_entry를 가리킨다.
    • key : 랜덤한 값으로 생성된 key를 추가로 가진다. (double free 체크하기 위함)
  • tcache_perthread_struct

    • counts[] : 각 tcache_bin 마다 현재 존재하는 chunk 수가 저장되어 있다.
    • entries[] : tcache_bin들의 배열이다.

tcache 구현부분

tcache

  • chunk의 사이즈가 tcache bin이 담을 수 있는 크기보다 더 크다면, 그냥 if문 탈출.
  • double free되었는지 체크.
    • free시에 tcache_entry->key값을 미리 생성된 랜덤 값으로 바꾸게 되는데, 만약 double free가 된 경우라면 이미 tcache_entry->key 값이 랜덤 값과 같게 된다. 하지만 같다고 해서 무조건 double free는 아닌 것이, 진짜진짜 우연으로 malloc 한 후에 넣은 데이터 값이 랜덤 값과 같을 수도 있다.
    • 그러므로 key값이 랜덤값과 같은 경우 (애초에 이 경우는 거의 일어나지 않음) tcache를 순회하면서 다른 chunk와 같은 주소를 가지고 있는지 (double free되지 않았는지 알아보는 확실한 방법) 확인해 보는 것이다.
  • 4465 ~ 4470 : 정상적인 경우에 해당하므로 tcache_bin에 집어넣는다.
    • 물론 이미 tcache_bin이 꽉 찼을 경우 (== 7)는 못 집어넣고 다음으로 넘어감.

tcache_put

tcache_put

  • key값을 tcache_key값 (미리 만들어진 랜덤값) 으로 바꾼다.
  • 그 후, e를 tcache_bin에 집어넣는다.
  • 해당 bin의 count값 증가시킴.

fastbin

fastbin_1

  • 다음 chunk의 크기가 CHUNK_HDR_SZ보다 작거나 같을 때, 혹은
    다음 chunk의 크기가 av->system_mem(av가 관리하고 있는 메모리의 크기)보다 크거나 같다면 fail이 true가 되어 에러가 출력된다.
  • free_perturb : chunk의 data영역을 perturb_byte로 채운다.
    perturb_byte가 0이 아닌경우에만 채운다.
  • atomic_store_relaxed : atomic하게 av->have_fastchunks를 true로 바꿔준다.

fastbin_2

  • 일단 이 부분은 LIFO 형태인 fastbin에 새로운 chunk를 달아주는 과정이다.
  • SINGLE_THREAD_P인 경우 어차피 data race가 발생하지 않으므로 그냥 바꿔주면 된다.
  • 그렇지 않은 경우, data race를 피해야 함.
    -> CAS(compare and swap) atomic 함수를 이용해서 해결한다.
  • catomic_compare_and_exchange_val_rel : CAS함수에 해당한다.
    • fb가 가리키는 값이 old2와 같으면 그 값을 p로 바꾼다.
    • 리턴값은 기존에 fb가 가리키고 있던 값이다.
    • 그러므로 기존 값이 old2와 같을 때에만 old값이 old2로 바뀌어서 while문을 탈출하게 된다.
  • 마지막 부분은 old와 현재 chunk의 크기가 다른 경우 에러를 출력하는 부분이다. (얘는 사실 왜 있는지 모르겠음. memory corruption때문인가)

unsorted & small & large

error handling

error

  • 여기는 에러 처리를 담당하는 부분이다.
  • chunk가 top에 해당한다면 감지.
  • nextchunk가 arena가 담당하는 영역을 벗어나도 감지. (top 메모리를 벗어났을 경우)
  • 현재 chunk의 inuse bit이 꺼졌을 경우 감지.
  • nextsize가 올바르지 않으면 감지.
  • 그 후에 free_perturb를 호출한다.

  • 메모리가 corrupt되지 않았는지 수시로 확인함.
  • doubly-linked list의 연결을 끊어준다.
  • 이후에는 largebin에 있는 경우에 해당함. (smallbin_range를 벗어나면서 fd_nextsize != NULL이 아닌 경우)

consolidate backward

consolidate_backward

  • 먼저 이전 chunk가 사용중이지 않은지 확인.
  • size에 consolidate 이후의 크기를 저장한다.
  • 만약 prev_size와 prev_chunk의 size값이 일치하지 않는다면 에러처리
  • unlink한다.

consolidate forward

consolidate_forward

  • 다음 chunk가 top이 아닐 때에만 일어남.
  • nextchunk의 inuse bit가 0인 경우에만 unlink를 하고, size값에 추가해준다.
  • nextchunk의 inuse bit가 1인 경우에는 다음 chunk를 병합할 수는 없으므로 inuse_bit을 0으로 만들어 준다.

unsorted_bin

set_head_foot

unsorted_bin

  • unsorted bin에 넣어주는 과정.
  • 특히 large_bin의 크기에 해당한다면 fd_nextsize, bk_nextsize를 NULL로 초기화한다.
  • nextchunk의 prev_size, 현재 chunk의 size값을 업데이트한다.

top

  • 만약 nextchunk == av->top이라면, 해당 chunk는 unsorted bin에 들어가지 않고 top chunk에 병합된다.

나머지

fastbin_consolidate

  • size가 FASTBIN_CONSOLIDATION_THRESHOLD 이상이 되면, fastbin 내부의 chunk들도 consolidation을 진행한다.
  • 만약 현재 av가 main_arena인지 아닌지에 따라 여러 처리를 해 준다. (수정 예정)
  • 마지막으로, mmap() 되었던 메모리일 경우, munmap을 호출해 준다.

malloc_consolidate

malloc_consolidate

  • fastbin을 모두 순회하며 fastbin을 NULL로 만들어 주고, 각 chunk들을 unsorted bin에 넣어준다.
  • av->have_fastchunks = false; 로 바꾼다.
  • 얘는 사실 _int_free 함수와 거의 비슷함.
  • 그래서 나머지 코드부분은 생략함.
profile
공부 내용 저장소

0개의 댓글