glibc中free函数详解

本文详细剖析了glibc中的free函数实现,包括检查hook函数、_int_free的chunk检查、TCACHE处理、fast bin的处理、chunk的合并以及对大chunk的特殊处理等关键步骤,揭示了内存管理的内部机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

__libc_free详解(tcache 略)

1. 检查是否存在 hook函数,如果有就执行

void
__libc_free (void *mem)
{
   
  mstate ar_ptr;
  mchunkptr p;                          /* chunk corresponding to mem */
/*
	1. 关于__free_hook,释放时会检查其会否为NULL,否的话就执行相应的函数
	2. __free_hook指向的函数,其调用的参数,为chunk中的内容
	3. 将__free_hook,改为system时,需要在chunk中写入 /bin/sh
	4. 将__free_hook,改为onegadget时,有时需要调整rsp
	5. 貌似是在__malloc_hook下面的realloc_hook,通过push调整

*/
  void (*hook) (void *, const void *)
    = atomic_forced_read (__free_hook);
  if (__builtin_expect (hook != NULL, 0)) //hook函数不是null,就执行__free_hook对应的函数并返回
    {
   
      (*hook)(mem, RETURN_ADDRESS (0));
      return;
    }

  if (mem == 0)                              /* free(0) has no effect */
    return;
	/*
		1. 用户指向的空间在chunk头下方0x10处,chunk头对用户是不可见的,free处理的就是chunk头
		2. 因此,需要获得chunk头的指针
	*/
  p = mem2chunk (mem); //将指向user data 的指针转化为指向 chunk的指针

  /*
  	1. 一般使用 mmap分配的chunk都非常的大,且chunk的地址在libc_base的上方固定偏移,因此可以用来泄漏libc的地址
  	2. 一般在没有size检查时使用
  */
  if (chunk_is_mmapped (p)) //如果chunk是mmap分配的,就用munmap_chunk()函数释放                /* release mmapped memory. */
    {
   
      /* See if the dynamic brk/mmap threshold needs adjusting.
	 Dumped fake mmapped chunks do not affect the threshold.  */
      if (!mp_.no_dyn_threshold
          && chunksize_nomask (p) > mp_.mmap_threshold
          && chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX
	  && !DUMPED_MAIN_ARENA_CHUNK (p))
        {
   
          mp_.mmap_threshold = chunksize (p);
          mp_.trim_threshold = 2 * mp_.mmap_threshold;
          LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
                      mp_.mmap_threshold, mp_.trim_threshold);
        }
      munmap_chunk (p);
      return;
    }

  MAYBE_INIT_TCACHE ();
	/*
		1. ar_ptr实际上不在heap数据段中,在libc中,是一个全局的变量
		2. 当释放small chunk是,ustored bin中指向的是main_area + 88
		3. 在ubuntu 16.04中,libc_base = main_area - 88 - 0x3c4b20
	*/
  ar_ptr = arena_for_chunk (p); //获得指向arena的指针
  _int_free (ar_ptr, p, 0); //调用init函数进行释放
    
}

2. _int_free()函数,对chunk进行检查

static void
_int_free (mstate av, mchunkptr p, int have_lock)
{
   
  INTERNAL_SIZE_T size;        /* its size */
  mfastbinptr *fb;             /* associated fastbin */
  mchunkptr nextchunk;         /* next contiguous chunk */
  INTERNAL_SIZE_T nextsize;    /* its size */
  int nextinuse;               /* true if nextchunk is used */
  INTERNAL_SIZE_T prevsize;    /* size of previous contiguous chunk */
  mchunkptr bck;               /* misc temp for linking */
  mchunkptr fwd;               /* misc temp for linking */

  size = chunksize (p);

  /* Little security check which won't hurt performance: the
     allocator never wrapps around at the end of the address space.
     Therefore we can exclude some size values which might appear
     here by accident or by "design" from some intruder.  */
    
    //第一个条件筛选掉一些特别大的size,第二个条件检查chunk是否对齐
  if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值