Post

[glibc 2.27] ptmalloc2 분석(3)

개요

이전 포스터에 이어서 glibc 2.27 버전에서 패치된 사항을 분석하고자 합니다. 새로운 개념이 등장한 것은 아니지만 많은 부분에서 수정이 이루어져서 포스터를 작성합니다. 앞선 포스터를 먼저 보시는 것을 추천드립니다!

Single Thread

__libc_malloc

우선, 해당 함수에서 아래와 같은 로직이 추가되었습니다. SINGLE_THREAD_P의 값이 True일 경우 아래와 같이 동적 할당을 받은 뒤 바로 리턴되는 것을 확인할 수 있습니다. 즉, 싱글 스레드일 경우 아래와 같이 arena_get 함수를 거치지 않고 바로 실행되도록 변경되었습니다.

💡 이렇게 변경된 이유는 싱글 스레드 일경우 main_arena만 존재하기 때문에 더 효율적으로 변경된 것을 확인할 수 있습니다.

1
2
3
4
5
6
7
if (SINGLE_THREAD_P)
  {
    victim = _int_malloc (&main_arena, bytes);
    assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
      &main_arena == arena_for_chunk (mem2chunk (victim)));
    return victim;
  }

_int_malloc

다음으로 해당 함수도 많은 패치가 이루어졌습니다. 우선 __libc_malloc와 같이 싱글 스레드 일 경우인 조건문이 몇개 추가되었습니다.

1
2
3
4
if (SINGLE_THREAD_P)
  *fb = victim->fd;
  
  ...

또한, smallbin에서 chunk를 가져와서 할당하는 과정에서 아래의 로직이 삭제되었습니다.

💡 해당 로직은 해제된 chunk를 병합하는 과정인데 이 과정이 삭제되었습니다.

1
2
if (victim == 0) /* initialization check */
  malloc_consolidate (av);

_int_free

__libc_free 함수에서 패치는 없기 때문에 바로 _int_free 함수를 분석하겠습니다. 우선 아래와 같이 lock하는 부분에서 변경이 있었습니다.

1
2
3
4
5
6
7
if (!have_lock)
  {
    __libc_lock_lock (av->mutex);
    fail = (chunksize_nomask (chunk_at_offset (p, size)) <= 2 * SIZE_SZ
	    || chunksize (chunk_at_offset (p, size)) >= av->system_mem);
    __libc_lock_unlock (av->mutex);
  }

또한, malloc 함수처럼 싱글 스레드일 때 처리하는 부분이 변경되었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (SINGLE_THREAD_P)
{
	/* Check that the top of the bin is not the record we are going to
	add (i.e., double free).  */
	if (__builtin_expect (old == p, 0))
		malloc_printerr ("double free or corruption (fasttop)");
	p->fd = old;
	*fb = p;
}

...

/* If we're single-threaded, don't lock the arena.  */
if (SINGLE_THREAD_P)
  have_lock = true;

fastbin chunk size 검증

malloc_consolidate 함수에서는 아래와 같이 fastbinchunk size를 검증하는 부분이 추가되었습니다.

1
2
3
4
5
	{
	  unsigned int idx = fastbin_index (chunksize (p));
	  if ((&fastbin (av, idx)) != fb)
	    malloc_printerr ("malloc_consolidate(): invalid chunk size");
	}

그리고 아래의 부분이 삭제되었습니다.

1
2
3
4
else {
  malloc_init_state(av);
  check_malloc_state(av);
}

결론

glibc 2.27에서 주요하게 변경된 부분은 다음과 같습니다.

  • SINGLE_THREAD_P 변수를 토대로 싱글스레드에 대한 조건문을 추가하면서 효율이 증가
  • fastbin의 chunk size 검증 추가
This post is licensed under CC BY 4.0 by the author.