glibc
最近在看malloc的源码,因此记录一下各主流版本之间的差别。
glibc-2.27
2.27增加了tcache
在malloc_consolidate中
1
2/*新增:检查从fastbin中取出的chunk的大小是否满足fastbin的索引,house-of-rabbit无法使用 */
unsigned int idx = fastbin_index (chunksize (p));在unlink中
1
2
3/*新增:检查其下一个chunk的prev_size是否和size相等,即使用house-of-einherjar时第一个chunk应该被放入到unsortedbin中*/
if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0))
malloc_printerr ("corrupted size vs. prev_size");
glibc-2.29
tcache_entry结构体中增加了key,防止doublefree
1
2
3
4
5
6typedef struct tcache_entry
{
struct tcache_entry *next;
/* This field exists to detect double frees. */
struct tcache_perthread_struct *key;
} tcache_entry;对在unsortedbin中即将取出的chunk和其nextchunk做检查
1
2
3
4
5
6
7
8
9
10
11
12
13
14/*新增:unsortedbin attack失效,house-of-storm无法使用*/
if (__glibc_unlikely (size <= 2 * SIZE_SZ)
|| __glibc_unlikely (size > av->system_mem))
malloc_printerr ("malloc(): invalid size (unsorted)");
if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ)
|| __glibc_unlikely (chunksize_nomask (next) > av->system_mem))
malloc_printerr ("malloc(): invalid next size (unsorted)");
if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size))
malloc_printerr ("malloc(): mismatching next->prev_size(unsorted)");
if (__glibc_unlikely (bck->fd != victim)
|| __glibc_unlikely (victim->fd != unsorted_chunks (av)))
malloc_printerr ("malloc(): unsorted double linked list corrupted");
if (__glibc_unlikely (prev_inuse (next)))
malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");在unlink前增加了对prev_size和size的判断
1
2/*新增:检查了prev_size和上一个chunk的size是否相等,house-of-einherjar不能使用*/
if (__glibc_unlikely (chunksize(p) != prevsize))
glibc-2.30&glibc-2.31
tcache_perthread_struct中的counts类型变为uint16_t类型
1
2
3
4
5typedef struct tcache_perthread_struct
{
uint16_t counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;如果tcache->counts[tc_idx]<=0则不会从tcache中取chunk
1
2
3
4
5
6if (tc_idx < mp_.tcache_bins
&& tcache
&& tcache->counts[tc_idx] > 0)
{
return tcache_get (tc_idx);
}将chunk从unsortedbin中取出放入到largebin时做了检查,增大了largebin attack的难度。
1
2
3
4if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
if (bck->fd != fwd)
malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
glibc-2.32
tcache中对e->next也就是fd指针做了加密,(&e->next>>12)<<12即为heap_base
1
2
3e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
#define PROTECT_PTR(pos, ptr)
((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))对fastbin的fd指针也做了相同的加密。
1
2/*新增:fastbin的fd指针被加密*/
p->fd = PROTECT_PTR (&p->fd, old);增加了很多指针是否对齐的检查