Daily Heap #6
14159 ワード
Overview
この文章から,
上記のバージョンを選択する基準は、最も基本的なglibc 2.23であり、tcacheといくつかの保護技術を追加したglibc 2.29であり、最新リリースUbuntu 21.10で使用されているglibc 2.34が作成されます.
まず,libc malloc()呼び出し malloc hookが空かどうか NULL以外の場合は、malloc hookの値を指定して関数ポインタとして実行 NULLの場合、int malloc()呼び出し に移動します.
int malloc()呼び出し
内部コードを表示すると、2つの変数が宣言されていることがわかります.
Hook
変数の宣言が完了したら、hook値がNULLであるかどうかを確認します.デフォルトではNULL値に初期化されているため、NULLでない場合はHook Overwriteで説明を続けます.
arena_get
Variable Declaration
リクエストのサイズが有効範囲内であるかどうか、および使用可能なarenaが存在するかどうかを決定する構文があります.
使用可能なarenaがあるかどうかを決定する構文について、パラメータとして渡されるav値がNULLである場合、
Reference https://m.blog.naver.com/eleexpert/140123898205
この文章から,
malloc()
関数とfree()
関数の挙動を深く検討する.glibc 2.23、glibc 2.29、glibc 2.34の3つのバージョンのため、glibcのバージョンによって詳細な動作の違いがあります.上記のバージョンを選択する基準は、最も基本的なglibc 2.23であり、tcacheといくつかの保護技術を追加したglibc 2.29であり、最新リリースUbuntu 21.10で使用されているglibc 2.34が作成されます.
malloc()
in glibc 2.23まず,
malloc()
のコールプロセスを簡単にまとめた.__libc_malloc()
関数の実装コードは次のとおりです.void *
__libc_malloc (size_t bytes)
{
mstate ar_ptr;
void *victim;
void *(*hook) (size_t, const void *)
= atomic_forced_read (__malloc_hook);
if (__builtin_expect (hook != NULL, 0))
return (*hook)(bytes, RETURN_ADDRESS (0));
arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
/* Retry with another arena only if we were able to find a usable arena
before. */
if (!victim && ar_ptr != NULL)
{
LIBC_PROBE (memory_malloc_retry, 1, bytes);
ar_ptr = arena_get_retry (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
}
if (ar_ptr != NULL)
(void) mutex_unlock (&ar_ptr->mutex);
assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
ar_ptr == arena_for_chunk (mem2chunk (victim)));
return victim;
}
「Hook Overwrite Exploit」は、Hookに関連する関数を処理する機会があるため、ここでは詳細に説明しません.内部コードを表示すると、2つの変数が宣言されていることがわかります.
mstate ar_ptr
の場合は、ブロックを割り当てる「arena」のptr値を指定するmalloc_state
構造を参照してください.void *victim
の変数は、ブロック割当てが完了した後に返される「mem」領域のアドレスを格納し、後で説明するコードで主な動作目標となる項目を関数を使用して「被害者」と命名するために使用される.Hook
変数の宣言が完了したら、hook値がNULLであるかどうかを確認します.デフォルトではNULL値に初期化されているため、NULLでない場合はHook Overwriteで説明を続けます.
arena_get
arena_get()
の動作はarenaです.cファイルで定義します.内容は次のとおりです.#define arena_get(ptr, size) do { \
ptr = thread_arena; \
arena_lock (ptr, size); \
} while (0)
受信したパラメータによってarena_lock()
マクロを再呼び出し,デッドロック防止プロセスを推定した._int_malloc()
arenaに対する事前準備が完了した後、_int_malloc()
関数を呼び出して実際のデータブロックを割り当てる.実装コード量が大きいため,ランダム分割解析を行った.Variable Declaration
3318 static void *
3319 _int_malloc (mstate av, size_t bytes)
3320 {
3321 INTERNAL_SIZE_T nb; /* normalized request size */
3322 unsigned int idx; /* associated bin index */
3323 mbinptr bin; /* associated bin */
3324
3325 mchunkptr victim; /* inspected/selected chunk */
3326 INTERNAL_SIZE_T size; /* its size */
3327 int victim_index; /* its bin index */
3328
3329 mchunkptr remainder; /* remainder from a split */
3330 unsigned long remainder_size; /* its size */
3331
3332 unsigned int block; /* bit map traverser */
3333 unsigned int bit; /* bit map traverser */
3334 unsigned int map; /* current word of binmap */
3335
3336 mchunkptr fwd; /* misc temp for linking */
3337 mchunkptr bck; /* misc temp for linking */
3338
3339 const char *errstr = NULL;
まず、「mbinptr」および「mchunkptr」はいずれもtypedef struct malloc_chunk*
と宣言されていることに注意してください.typedef struct malloc_chunk* mchunkptr;
typedef struct malloc_chunk *mbinptr;
「INTERNAL SIZE T」はsize tデータ型と同様にx 86で4、x 86-64で8バイトである.リクエストのサイズが有効範囲内であるかどうか、および使用可能なarenaが存在するかどうかを決定する構文があります.
3341 /*
3342 Convert request size to internal form by adding SIZE_SZ bytes
3343 overhead plus possibly more to obtain necessary alignment and/or
3344 to obtain a size of at least MINSIZE, the smallest allocatable
3345 size. Also, checked_request2size traps (returning 0) request sizes
3346 that are so large that they wrap around zero when padded and
3347 aligned.
3348 */
3349
3350 checked_request2size (bytes, nb);
3351
3352 /* There are no usable arenas. Fall back to sysmalloc to get a chunk from
3353 mmap. */
3354 if (__glibc_unlikely (av == NULL))
3355 {
3356 void *p = sysmalloc (nb, av);
3357 if (p != NULL)
3358 alloc_perturb (p, bytes);
3359 return p;
3360 }
checked_request2size()
defineによりマクロとして定義され、コードは以下の通りである.#define checked_request2size(req, sz) \
if (REQUEST_OUT_OF_RANGE (req)) { \
__set_errno (ENOMEM); \
return 0; \
} \
(sz) = request2size (req);
要求された寸法が有効範囲内であれば、整列のために加工された寸法を返します.使用可能なarenaがあるかどうかを決定する構文について、パラメータとして渡されるav値がNULLである場合、
sysmalloc()
がmmap()
からblockを取得するように呼び出される.このコースで使用している__glibc_unlikely()
については、リンクでKernelで効率を向上させるための使用可能な関数の詳細を参照してください.Reference
Reference
この問題について(Daily Heap #6), 我々は、より多くの情報をここで見つけました https://velog.io/@insp3ct0r_/Daily-Heap-6テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol