(glibc) malloc - 3
* ASLR is disabled
application’s initial heap
프로그램이 malloc()
등 직접 heap을 할당받는 코드를 실행하지 않더라도, 기본적으로 ` 0x21000`(132KB) 크기의 initial heap을 가지고 있으며 이 heap은 main_arena에 해당한다.
1
2
3
4
5
6
7
00400000-00401000 r-xp 00000000 08:01 1442324 /home/umbum/heap\_study/no\_malloc
00600000-00601000 r--p 00000000 08:01 1442324 /home/umbum/heap\_study/no\_malloc
00601000-00602000 rw-p 00001000 08:01 1442324 /home/umbum/heap\_study/no\_malloc
00602000-00623000 rw-p 00000000 00:00 0 [heap]
7ffff7a0d000-7ffff7bcd000 r-xp 00000000 08:01 548924 /lib/x86\_64-linux-gnu/libc-2.23.so
...
너무 크지 않은 요청에 대해 main_arena에 요청을 처리할 수 있을 정도의 빈 공간이 있는 경우이면 arena의 일부분을 chunk로 반환한다.
1
2
3
4
5
6
7
==Heap malloc test==
Before malloc
After malloc::0x602830 (size:4096)
1
2
00602000-00623000 rw-p 00000000 00:00 0 [heap]
mchunkptr
은 64bit에서는 0x10
이전을 가리키므로, 거기서 부터 출력해보면,
1
2
3
4
5
gdb-peda$ x/12x 0x602820
0x602820: 0x0000000000000000(prev\_size) 0x0000000000001011(size|flag) => chunk의 시작지점
0x602830: 0x0000000074736574(payload) 0x0000000000000000
payload
에는 “test” 문자열이 잘 들어간 것을 확인할 수 있다. size|flag
에는 0x1011
이 들어갔는데, 요청한 payload size 0x1000
에 size|flag
를 나타내기 위한 0x8
bytes를 확보하면서 16의 배수로 align했기 때문에 0x10
이 추가되었고, P(0x1)
flag가 지정되어 있음을 알 수 있다. 무조건 0x10
을 반올림 하는게 아니라 0x8
byte를 확보한 다음 align하는 것이다. 64bit os에서 24만큼 요청하면 24+8이 되어 32가 되므로, align시 추가되는 byte가 없어 0x21
이 된다. 25부터 0x31
.
heap growth
할당할 heap memory가 부족한 경우 malloc()
은 내부적으로 brk() / mmap()
system call 중 하나를 호출한다.
MMAP_THRESHOLD가 넘는 크기의 할당을 요청하는 경우 : mmap()
mmap()
을 사용해 아예 다른 곳에 메모리를 할당한다. MMAP\_THRESHOLD
값이 따로 설정되지 않은 경우에는 dynamic하게 결정된다.
1
2
3
4
5
6
7
==Heap malloc test==
Before malloc
After malloc::0x7ffff7fb7010 (size:151552)
1
2
3
4
5
6
7
8
9
10
11
12
13
00400000-00401000 r-xp 00000000 08:01 1442317 /home/umbum/heap\_study/heap\_test
00600000-00601000 r--p 00000000 08:01 1442317 /home/umbum/heap\_study/heap\_test
00601000-00602000 rw-p 00001000 08:01 1442317 /home/umbum/heap\_study/heap\_test
00602000-00623000 rw-p 00000000 00:00 0 [heap]
7ffff7a0d000-7ffff7bcd000 r-xp 00000000 08:01 548924 /lib/x86\_64-linux-gnu/libc-2.23.so
7ffff7bcd000-7ffff7dcd000 ---p 001c0000 08:01 548924 /lib/x86\_64-linux-gnu/libc-2.23.so
7ffff7dcd000-7ffff7dd1000 r--p 001c0000 08:01 548924 /lib/x86\_64-linux-gnu/libc-2.23.so
7ffff7dd1000-7ffff7dd3000 rw-p 001c4000 08:01 548924 /lib/x86\_64-linux-gnu/libc-2.23.so
7ffff7dd3000-7ffff7dd7000 rw-p 00000000 00:00 0
7ffff7dd7000-7ffff7dfd000 r-xp 00000000 08:01 548898 /lib/x86\_64-linux-gnu/ld-2.23.so
7ffff7fb7000-7ffff7fe0000 rw-p 00000000 00:00 0 !!!! 여기에 할당 !!!!
...
추가적인 메모리를 할당하기 위해 syscall mmap()
을 사용하는 것을 알 수 있다.
1
2
3
4
5
...
mmap(NULL, 155648, PROT\_READ|PROT\_WRITE, MAP\_PRIVATE|MAP\_ANONYMOUS, -1, 0) = 0x7ffff7fb7000
write(1, "After malloc::0x7ffff7fb7010 \n", 29After malloc::0x7ffff7fb7010 ) = 29
...
free()
하면 munmap()
을 호출한다.
1
2
3
munmap(0x7f572c15c000, 155648) = 0
write(1, "After free\n", 11After free) = 11
작은 크기를 요청했는데 arena에 공간이 부족한 경우 : brk()
brk()
는 program break 위치를 변경해서 data segment size를 조정하는 system call이다. * program break는 uninitialized data segment의 끝 바로 다음 위치를 의미한다. 이를 이용해 top chunk의 크기를 증가시켜 여분의 공간을 확보하거나 줄일 수 있다. * top chunk : arena의 최상단 chunk
1
2
3
4
5
6
7
8
9
10
11
12
13
==Heap malloc test==
Before malloc
After malloc::0x602830 (size:4096)
After malloc::0x603840 (size:4096)
After malloc::0x604850 (size:4096)
.......
After malloc::0x625a60 (size:4096)
After malloc::0x626a70 (size:4096)
initial heap의 size가 증가했다.
1
2
00602000-00644000 rw-p 00000000 00:00 0 [heap]
arena를 확장하기 위해 brk()
를 사용한다는 것을 알 수 있다.
1
2
3
4
5
6
...
write(1, "After malloc::0x621a20 (size:40"..., 36After malloc::0x621a20 (size:4096)) = 36
brk(0x644000) = 0x644000
write(1, "After malloc::0x622a30 (size:40"..., 36After malloc::0x622a30 (size:4096)) = 36
...
free()
에도 brk()
를 사용한다
1
2
3
brk(0x623000) = 0x623000
write(1, "After free\n", 11After free) = 11