static void *
sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
{
long int size;
/*
Round up size to nearest page. For mmapped chunks, the overhead is one
SIZE_SZ unit larger than for normal chunks, because there is no
following chunk whose prev_size field could be used.
See the front_misalign handling below, for glibc there is no need for
further alignments unless we have have high alignment.
*/
if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
size = ALIGN_UP (nb + SIZE_SZ, pagesize);
else
size = ALIGN_UP (nb + SIZE_SZ + MALLOC_ALIGN_MASK, pagesize);
/* Don't try if size wraps around 0. */
if ((unsigned long) (size) <= (unsigned long) (nb))
return MAP_FAILED;
char *mm = (char *) MMAP (0, size,
mtag_mmap_flags | PROT_READ | PROT_WRITE,
extra_flags);
if (mm == MAP_FAILED)
return mm;
#ifdef MAP_HUGETLB
if (!(extra_flags & MAP_HUGETLB))
...
malloc 할 때 일반적으로 큰 사이즈를 요청하면, brk나 sbrk로 program break를 쭉 늘리거나 감당할만하면, 탑 청크에서 떼주는데, malloc(0x200000) 이런 식으로 엄청 크게 줘버리면, 위 sysmalloc_mmap을 통해 mmap syscall을 부른다.
이때 커널에서 리턴받은 메모리와 libc가 로드된 주소와의 오프셋이 일정하다는 특징을 통해 libc leak이 가능하다.
libc 바로 앞에 딱 달라붙어있는게 mmap으로 할당받은 곳이다.