ctfwiki--arena

15753 ワード

参照リンク:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/heap_structure-zh/
arena
プライマリ・スレッドでも新しく作成されたスレッドでも、メモリを初めて申請するときに独立したarenaがあります.異なるシステムの場合、arenaの数は以下の通りです.
For 32 bit systems:
     Number of arena = 2 * number of cores.
For 64 bit systems:
     Number of arena = 8 * number of cores.
各スレッドに対応するarenaがあるわけではないことは明らかです.スレッド数がコア数の2倍より大きい場合、必然的にスレッドが待機状態にあるため、各スレッドにarenaを割り当てる必要はありません.
threadとは違ってmain_arenaは申請したheapではなく、libc.でグローバル変数です.soのデータセグメント.
heap_info
heap_infoは、メモリを申請したときに発生した情報を記録するために使用されます.プログラムが実行されたばかりのとき、各スレッドにはheap領域がありません.(うんうん、そうらしいけど、mallocの後になってから)また、一般申請のheapは不連続なので、異なるheap間のリンク構造を記録する必要があります.
このデータ構造は、memory mapping segmentから申請されたメモリに特化して用意され、すなわち非プライマリスレッドに用意されている.
メインスレッドは、sbrk()拡張プログラムbreak locationによって得ることができる(mmsに直接触れる).
heap_infoの主な構造は以下の通りです.
#define HEAP_MIN_SIZE (32 * 1024)
#ifndef HEAP_MAX_SIZE
# ifdef DEFAULT_MMAP_THRESHOLD_MAX
#  define HEAP_MAX_SIZE (2 * DEFAULT_MMAP_THRESHOLD_MAX)
# else
#  define HEAP_MAX_SIZE (1024 * 1024) /* must be a power of two */
# endif
#endif

/* HEAP_MIN_SIZE and HEAP_MAX_SIZE limit the size of mmap()ed heaps
   that are dynamically created for multi-threaded programs.  The
   maximum size must be a power of two, for fast determination of
   which heap belongs to a chunk.  It should be much larger than the
   mmap threshold, so that requests with a size just below that
   threshold can be fulfilled without creating too many heaps.  */

/***************************************************************************/

/* A heap is a single contiguous memory region holding (coalesceable)
   malloc_chunks.  It is allocated with mmap() and always starts at an
   address aligned to HEAP_MAX_SIZE.  */

typedef struct _heap_info
{
  mstate ar_ptr; /* Arena for this heap. */
  struct _heap_info *prev; /* Previous heap. */
  size_t size;   /* Current size in bytes. */
  size_t mprotect_size; /* Size in bytes that has been mprotected
                           PROT_READ|PROT_WRITE.  */
  /* Make sure the following data is properly aligned, particularly
     that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
     MALLOC_ALIGNMENT. */
  char pad[-6 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;
この構造は主に,(1)スタックに対応するarenaのアドレス(2)1つのスレッドに複数のスタックがある可能性がある(これは正常ではないか?)を含むスタックの基本情報を記述するものである.prevは前のheap_を記録しましたinfoのアドレス.単一チェーンテーブルリンクheap_info(3)sizeは現在のスタックの大きさ(4)の最後の部分が位置合わせされていることを示しています(私にもわかりませんよね?)
malloc_state
この構造は、スタックを管理するために使用されます.各arenaの現在の申請メモリの具体的な状態を記録します.例えば、空きchunkがあるかどうか、どの大きさの空きchunkがあるかなどです.thread arenaでもmain arenaでもmalloc_は1つしかありませんstate構造.threadのarenaが複数ある可能性があるので、malloc_state構造は最新申請のarenaにあります.
main arenaのmalloc_stateはheap segmentの一部ではなくlibcに格納グローバル変数である.soのデータセグメント.構造は次のとおりです.
struct malloc_state {
    /* Serialize access.  */
    __libc_lock_define(, mutex);

    /* Flags (formerly in max_fast).  */
    int flags;

    /* Fastbins */
    mfastbinptr fastbinsY[ NFASTBINS ];

    /* Base of the topmost chunk -- not otherwise kept in a bin */
    mchunkptr top;

    /* The remainder from the most recent split of a small request */
    mchunkptr last_remainder;

    /* Normal bins packed as described above */
    mchunkptr bins[ NBINS * 2 - 2 ];

    /* Bitmap of bins, help to speed up the process of determinating if a given bin is definitely empty.*/
    unsigned int binmap[ BINMAPSIZE ];

    /* Linked list, points to the next arena */
    struct malloc_state *next;

    /* Linked list for free arenas.  Access to this field is serialized
       by free_list_lock in arena.c.  */
    struct malloc_state *next_free;

    /* Number of threads attached to this arena.  0 if the arena is on
       the free list.  Access to this field is serialized by
       free_list_lock in arena.c.  */
    INTERNAL_SIZE_T attached_threads;

    /* Memory allocated from the system in this arena.  */
    INTERNAL_SIZE_T system_mem;
    INTERNAL_SIZE_T max_system_mem;
};
(1)_libc_lock_define(,mutex):この変数は、プログラムが同じ割当て領域にシリアルアクセスすることを制御するために使用されます.1つのスレッドが割当て領域を取得した後、他のスレッドが割当て領域にアクセスするには、スレッド割当てが完了するまで待たなければなりません.(2)flags:bit 0がfast bin chunkを記録しているかどうか、bit 1が連続した仮想アドレス空間を返すことができるかどうかを識別するなど、いくつかの割当領域のフラグが記録されている.具体的には以下の通りです.
/*
   FASTCHUNKS_BIT held in max_fast indicates that there are probably
   some fastbin chunks. It is set true on entering a chunk into any
   fastbin, and cleared only in malloc_consolidate.
   The truth value is inverted so that have_fastchunks will be true
   upon startup (since statics are zero-filled), simplifying
   initialization checks.
 */

#define FASTCHUNKS_BIT (1U)

#define have_fastchunks(M) (((M)->flags & FASTCHUNKS_BIT) == 0)
#define clear_fastchunks(M) catomic_or(&(M)->flags, FASTCHUNKS_BIT)
#define set_fastchunks(M) catomic_and(&(M)->flags, ~FASTCHUNKS_BIT)

/*
   NONCONTIGUOUS_BIT indicates that MORECORE does not return contiguous
   regions.  Otherwise, contiguity is exploited in merging together,
   when possible, results from consecutive MORECORE calls.
   The initial value comes from MORECORE_CONTIGUOUS, but is
   changed dynamically if mmap is ever used as an sbrk substitute.
 */

#define NONCONTIGUOUS_BIT (2U)

#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)

/* ARENA_CORRUPTION_BIT is set if a memory corruption was detected on the
   arena.  Such an arena is no longer used to allocate chunks.  Chunks
   allocated in that arena before detecting corruption are not freed.  */

#define ARENA_CORRUPTION_BIT (4U)

#define arena_is_corrupt(A) (((A)->flags & ARENA_CORRUPTION_BIT))
#define set_arena_corrupt(A) ((A)->flags |= ARENA_CORRUPTION_BIT)
(3)fastbinsY[NFASTBINS]各fast chunkチェーンテーブルヘッダを格納するポインタ(4)topが分配領域を指すtop chunk(5)last_reminderの最新のchunk分割後の残りの部分(6)binsは、unstored bin,small bins,large binsのchunkチェーンテーブル(7)binmap ptmallocが、あるbinに空きchunkが含まれているか否かをビットで識別するために使用される.