ptmalloc | free 总体流程简述 | 无原子优化相关
当前流程 不考虑 开启原子优化
Public_fREe(void *mem)
- __free_hook == null ? pass : __free_hook(mem) # 如果 __free_hook 不为 null , 调用 __free_hook
- mem == null ? return; : mem2chunk(mem) => p; # 检测 mem 是否为 null , 如果为null , 直接return , 无影响
- if HAVE_MMAP # 检测 HAVE_MMAP 标识符
- chunk_is_mmaped(p) # 检测是否是 mmap 分配的
- !mp_.no_dyn_threshold && p->size > mp_.mmap_threshold && p->size <= DEFAULT_MMAP_THRESHOLD_MAX # 检测 动态调整 mmap_threshold 是否开启 和 条件是否满足 ([mp_,mmap_threshold + 1 , DEFAULT_MMAP_THRESHOLD_MAX ])
- mp_.mmap_threshold = chunksize (p); # 调整 分配阈值为 chunksize(p)
- mp_.trim_threshold = 2 * mp_.mmap_threshold # 调整 收缩阈值
- munmap_chunk(p) # 解除映射
- ar_ptr = arena_for_chunk(p); # 根据 chunk 获取 arena 的指针
- 对 分配区 尝试加锁
- _int_free(ar_ptr, p); # 调用 _int_free 执行实际的释放工作
- 对 分配去 解锁
_int_free(mstate av, mchunkptr p)
- 检测1 : p > -size || (misaligned_chunk (p)
- 报错标志 : free(): invalid pointer
- 检测内容 : 指针地址是否溢出 , 指针的地址 是否对齐
- 相关参数 :
- 检测2 : size < MINSIZE
- 报错标志 : free(): invalid size
- 检测内容 : chunk size 是否 大于 MINSIZE
- 相关参数:
- size <= get_max_fast () # fastbin chunk
- if TRIM_FASTBINS # 检测 TRIM_FASTBINS 标识符
- 作用 : 如果该标识符为 True , 靠近 top chunk 的 fastbin 不会进入该逻辑进行处理
- 检测 1: chunk_at_offset (p, size)->size <= 2 * SIZE_SZ || chunksize (chunk_at_offset (p, size)) >= av->system_mem
- 报错标志: free(): invalid next size (fast)
- 检测内容 : 下一个 chunk 的 size 是否 <= MINSIZE 或者 大于 分配内存总量
- 检测 2 : *fb == p
- 报错标志 : double free or corruption (fasttop)
- 检测内容 : 对应大小的 fastbin 链表表头 的 chunk 和 即将要 free 的 chunk 是否相同 , 即 double free # 这里是 fastbin attack 中 double free 的 利用原理
- 相关参数 :
- unsigned int idx = fastbin_index(size)
- fb = &fastbin (av, idx)
- 检测 3 : fb != NULL && fastbin_index(chunksize(fb)) != idx
- 报错标志 : invalid fastbin entry (free)
- 检测内容 : 检测 对应fastbin 的 idx 和 p 的 idx 是否相同
- 相关参数 :
- unsigned int idx = fastbin_index(size)
- fb = &fastbin (av, idx)
- 加入 链表表头
- if chunk_is_mmapped(p) : | mmap 分配的 chunk # 原为 else 的 处理 ,在最下方
- munmap_chunk (p); | 使用 munmap_chunk 解除映射
- if !chunk_is_mmapped(p) : # 不是 mmap 分配的 chunk # 此处 是原代码的判断 , 为了便于查看 , 将 mmap 分配内存的处理调整到 上方
- 检测 1 : p == av->top
- 报错标志 : double free or corruption (top)
- 检测内容 : p 是否是 top chunk
- 检测 2 : next_chunk >= av->top + chunksize(av->top)
- 报错标志 : double free or corruption (out)
- 检测内容 : next_chunk 是否超过了 main_arena 的 范围 , 地址溢出?
- 相关参数 :
- nextchunk = chunk_at_offset(p , size)
- 检测 3 : !prev_inuse(next_chunk)
- 报错标志 : double free or corruption (!prev)
- 检测内容 : 检测当前 chunk 是否正在使用
- 相关参数 :
- nextchunk = chunk_at_offset(p , size)
- 检测 4 : nextchunk->size <= 2 * SIZE_SZ || nextsize >= av->system_mem
- 报错标志 : free(): invalid next size (normal)
- 检测内容 : 检测下一个 chunk 的大小是否在合理范围内 [ 2 * SIZE_SZ : av->system_mem]
- 相关参数 :
- nextsize = chunksize(nextchunk)
- nextchunk = chunk_at_offset(p , size)
- consolidate forward | 前向合并
- 前置条件 : !prev_inuse(p) # 检测 前一个 chunk 是否在使用中
- 操作过程 :
- prevsize = p->prev_size
- size += prevsize # 增加 size 的 长度
- p = chunk_at_offset(p , - prevsize) # 设置 p 的 新位置
- unlink(p , bck , fwd) # unlink 操作 , 将前一个 chunk 从空闲 chunk 链表中移除
- consolidate backward | 后向合并
- 前置条件 : nextchunk != av->top && !nextinuse # 检测 下一个 chunk 是不是 topchunk 并且下一个 chunk 空闲
- 相关参数 :
- nextchunk = chunk_at_offset(p , size)
- nextinuse = inuse_bit_at_offset(nextchunk, nextsize) | 获取 nextchunk 的使用状态
- 操作过程:
- unlink(nextchunk, bck, fwd) | unlink 下一个chunk
- size += nextsize
- else :# 下一个 chunk 不空闲
- clear_inuse_bit_at_offset(nextchunk, 0) # 设置当前 chunk 的使用状态为 空闲
- if nextchunk != av->top : # 下一个 chunk 不是 top chunk 时 , 放入 unsorted bin
- 检测 1 : fwd->bk != bck
- 报错标志 : free(): corrupted unsorted chunks
- 检测内容 : 检测 unsorted_bin 的第一个 chunk 的bk 是否指向 &unsorted_bin_list
- 相关参数 :
- bck = unsorted_chunks(av)
- fwd = bck->fd
- 放入链表尾部:
- 操作 :
- p->fd = fwd; p->bk = bck; | unsorted bin attack 的原理
- bck->fd = p;fwd->bk = p;
- if !in_smallbin_range(size) | large bin
- p->fd_nextsize = NULL; p->bk_nextsize = NULL
- set_head(p, size | PREV_INUSE); # 设置 p 的 size 域
- set_foot(p, size) # 设置 p 的 next_chunk 的 prev_size
- else: # 下一个 chunk 是 top chnk
- size += nextsize | size 加上 topchunk的size
- av-top = p | 将 top chunk 的地址 设置为 p
- if (size) >= FASTBIN_CONSOLIDATION_THRESHOLD | 如果合并后 size > fastbin 整合的阈值
- if hava_fastchunks(av) | 如果 有 fastbin chunk
- malloc_consolidate(av) | 对fastbin chunks 进行一次整合 , 整合 fastbin chunk 到 unsorted bin 中
- if (av == &main_arena) | 判断 当前 arena 是不是主分配区
- if ( chunksize(av->top) > mp_.trim_threshold) | 判断 top chunk 的大小是否超过了heap 的收缩阈值
- sYSTRIm(mp_.top_pad , av) | 调用 sYSTRIm 进行收缩
- else : | 非主分配区
- heap_info *heap = heap_for_ptr(top(av));
- assert(heap->ar_ptr == av);
- heap_trim(heap, mp_.top_pad); | 尝试用 heap_trim 收缩 子分配区
本文标题:ptmalloc | free 总体流程简述 | 无原子优化相关
本文链接:https://www.haomeiwen.com/subject/nbrvdqtx.html
网友评论