Tcache
这一篇开始复习tcache
Tcache是glibc2.27后新增加的一种,结构体
1 | /* We overlay this structure on the user-data portion of a chunk when |
可以看到里面就是指向下一个空间的指针
1 | /* There is one of these for each thread, which contains the |
tcache_perthread_struct
里面是两个数组个数是TCACHE_MAX_BINS(默认是64,也就是说和smallbin的范围差不多),count是各个大小tcache的实时数量(它用的是char,毕竟数不大,省空间)。
entries数组里就是各个大小Tcache的头部指针
1 | /* Caller must ensure that we know tc_idx is valid and there's room |
可以看到,put(free)还是get(malloc)操作,无论是对比smallbin还是fastbin都是可以忽略不计的检查(对范围和大小进行了简单检查),
没有对齐检查,
没有inuse检查,
没有size检查,
没有链表指针检查,
基本上是你往指针域写哪儿,下一步它就跳哪儿。
Tcache是FIFO,每个Tcache最多可以放7个
简单说一下它的运行逻辑
它就像一个空间更大,更优先的容器空间(像fastbin),在一定范围里的内存都会放进去,也会优先从里面取。
每一次malloc(0x400以下),先查看对应的Tcache里是否有chunk,有就返回(在libc_malloc里)。
如果没有,就接着进入int_malloc,会按顺寻依次查看fastbin和smallbin中的chunk
- 此时,如果有符合条件的chunk且Tcache没满,就把第一个返回,其余的塞到Tcache,直到Tcache满。
如果遍历过程中,Tcache满了,就直接从bin中返回一个chunk(符合条件)
如果还没有,执行unsorted bin大循环(在这之前还是会执行consolidate,将fastbin合并并放进unsorted bin),遍历和操作每一个,直到遍历结束或者达到上限(1000)
- 如果遇到比我们request大的chunk,切割并
返回
,剩下的还是unsorted bin - 如果遇到和我们request一样大的chunk
- 如果Tcache已满,直接返回
- 如果Tcache没满,继续循环
- 如果最后Tcahe满,直接返回
- 如果Tcahe没满,最后从Tcache返回
- 如果遇到比我们request小的额chunk,将其放入相应bin,并继续循环。
- 如果遇到比我们request大的chunk,切割并
easy_heap
漏洞:
1 | while ( 1 ) |
off by null实现unlink,使得正在被使用的chunk也被包含在,unsorted bin.
但是我们很难去改变pre_size,直接覆写是不行的,但是我们可以通过unsorted bin合并,使pre_size被写入,由此实现。
1 |
|