tcache란?
thread local cache는 멀티 스레드 환경에서 메모리 할당 속도를 높이기 위한 것으로 각 스레드에 독립적으로 할당되는 캐시 저장소이다.
작은 단위의 메모리는 arena를 참조하지 않고 바로 메모리를 할당한다.
tcache는 glibc 버전 2.26에서 도입되었으며, 멀티 스레드 환경에 더욱 최적화된 메모리 관리 메커니즘을 제공한다.
tcache의 특징
- 각 스레드는 64개의 tcache를 가지고 있다.
- tcache는 LIFO방식으로 사용되는 단일 연결리스트이며, 하나의 tcache는 같은 크기의 chunk들만 보관한다.
- 리눅스는 각 tcache에 보관할 수 있는 chunk의 갯수를 7개로 제한하고 있다.
- tcache에 들어간 chunk들은 병합되지 않는다.
- tcache에는 32 ~ 1040 바이트 이하(fastbin과 smallbin)의 크기를 갖는 chunk들이 보관된다. 이 범위에 속하는 chunk들은 할당 및 해제될 때 tcache를 가장 먼저 조회한다.
- chunk가 보관될 tcache가 가득 찼을 경우에는 적절한 bin으로 분류된다.
- tcache는 각 스레드가 고유하게 갖는 캐시이기 때문에 ptmalloc은 레이스 컨디션을 고려하지 않고 이 캐시에 접근할 수 있다.
- tcache는 보안 검사가 많이 생략되어 공격자들에게 힙 익스플로잇의 도구로 사용된다.
tcache의 동작방식
간단한 코드를 보며 tcache의 동작방식에 대해 알아보자.
// gcc -o tcache_ex tcache_ex.c -no-pie
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr = malloc(0x10);
char *ptr2 = malloc(0x20);
char *ptr3 = malloc(0x30);
free(ptr);
free(ptr2);
free(ptr3);
ptr = malloc(0x10);
ptr2 = malloc(0x20);
ptr3 = malloc(0x30);
}
free(ptr); 직후 break를 건다.
힙 페이지 시작 부분에 0x251 의 size를 가진 heap chunk가 존재하는 것을 알 수 있다. 이는 malloc 호출시 tcache_init 함수를 통해 tcache_perthread_struct 구조체가 힙 영역에 할당된 것이다.
tcache에 chunk가 1개 들어가서 tcache_count가 1 증가한 것을 알 수 있고 chunk의 주소가 적혀있는것도 볼 수 있다.
두 번째 free 직후를 보자.
tcache_count도 각각의 영역에 써졌다. chunk의 주소가 쓰여진 것을 알 수 있다.
세 번째 free 직후를 보자.
tcache_count 역시 각각의 영역에 써졌다. chunk의 주소도 쓰였다.
tcache에서 chunk가 없어졌고 tcache_count가 1 줄어든 것을 볼 수 있다.
8개를 free했을 경우
같은 크기를 관리하는 tcache에는 최대 7개까지 chunk가 삽입가능하다. 아래의 코드는 8개의 chunk를 할당, 해제하는 코드이다.
// gcc -o tcache_escape tcache_escape.c -no-pie
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr[8];
int i;
for(i=0;i<=7;i++) {
printf("malloc !\n");
ptr[i] = malloc(0x20);
}
for(i=0;i<=7;i++) {
printf("free!\n");
free(ptr[i]);
}
}
<틀린 부분이 있다면 비난과 욕설을 해주세요>
'포너블 > Heap' 카테고리의 다른 글
Tcache function(2.31) (0) | 2023.09.22 |
---|---|
Tcache function (0) | 2023.09.22 |
free 소스코드 분석(libc 2.27) (0) | 2023.08.28 |
malloc 소스코드 분석(libc 2.27) (0) | 2023.08.23 |
free 소스코드 분석(libc 2.23) (0) | 2023.08.16 |