Glibc-2.29 新增的防护机制
TOC
1. free 1.1. tcache 1.2. chunk extend 2. malloc 2.1. unsorted bin 2.2. top chunk
下面我介绍几种在 glibc-2.29 中增加的防护机制,由于本人才疏学浅, 可能仅是冰山一角。
文章对照的是 glibc-2.27 和 glibc-2.29 。
free tcache 最明显的就是tcache。
来自源码:glibc-2.29/malloc/malloc.c:4197
if (__glibc_unlikely (e->key == tcache)) { tcache_entry *tmp; LIBC_PROBE (memory_tcache_double_free, 2 , e, tc_idx); for (tmp = tcache->entries[tc_idx]; tmp; tmp = tmp->next) if (tmp == e) malloc_printerr ("free(): double free detected in tcache 2" ); }
这里会对tcache链表上的所有chunk进行对比,检测是否有重复,这让原本在glibc-2.27和glibc-2.28肆虐的tcache double free攻击很难实施,但是鉴于tcache的特性,tcache的利用还是要比其他的bins方便很多。
chunk extend chunk extend也是很好用的攻击方式之一,但是在glibc-2.29中增加了新的检查,这将会增大chunk extend的难度。
来自源码:glibc-2.29/malloc/malloc.c:4334
if (!prev_inuse (p)) { prevsize = prev_size (p); size += prevsize; p = chunk_at_offset (p, -((long ) prevsize)); if (__glibc_unlikely (chunksize (p) != prevsize)) malloc_printerr ("corrupted size vs. prev_size while consolidating" ); unlink_chunk (av, p); }
在glibc-2.29中新增了prevsize的检查机制,在合并的时候会判断prev_size和要合并chunk的size是否相同。
malloc unsorted bin 原本这里仅仅有size检查。
来自源码:glibc-2.29/malloc/malloc.c:3742
bck = victim->bk; size = chunksize (victim); mchunkptr next = chunk_at_offset (victim, size); 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)" );
然后在glibc-2.29中,增加了如下检查:
对下一个相邻chunk的size检查
对下一个相邻chunk的prev_size进行检查
检查unsorted bin双向链表的完整性,对unsorted bin attack可以说是很致命的检查
对下一个chunk的prev_inuse位进行检查
这么多的检查,将使得unsorted bin更难利用。
下面这个检查早在glibc-2.28就有了,这里提一下,主要是防护unsorted bin attack。
来自源码:glibc-2.29/malloc/malloc.c:3976
if (__glibc_unlikely (bck->fd != victim)) malloc_printerr ("malloc(): corrupted unsorted chunks 3" ); unsorted_chunks (av)->bk = bck;bck->fd = unsorted_chunks (av);
top chunk 对于top chunk增加了size检查,遏制了House of Force攻击。
来自源码:glibc-2.29/malloc/malloc.c:4111
victim = av->top; size = chunksize (victim); if (__glibc_unlikely (size > av->system_mem)) malloc_printerr ("malloc(): corrupted top size" );