kfree机制
1是快路径,其余的2、3、4、5都是慢路径的不同情况;
源码解析
slub中有如下成员:
counters是inuse、objects、frozen的联合体,便于一次性将三个值一起赋值、拷贝;
inuse表示slub中已经分割出去的对象的数目;
frozen是一个状态位表示slub是否在当前cpu的partial链表中;
do_slab_free源码如下:https://elixir.bootlin.com/linux/v5.10/source/mm/slub.c#L3090
首先通过page == c->page来判断是不是当前cpu的slab,如果是,则直接插入;如果不是,就走__slab_free:https://elixir.bootlin.com/linux/v5.10/source/mm/slub.c#L2961
一个do-while循环:
可以看到free的时候是要inuse-=cnt减去释放的数量的;
!new.inuse表示这个slub已经变成empty了,!prior是指freelist为NULL,也就是说slub是full的,这两种情况下,都有可能(还有看是不是在cpu的partial中)要进行移动,所以紧接着用!was_frozen表示不在当前cpu->partial的链表中,因此要分情况讨论移动;第一种情况kmem_cache_has_cpu_partial表示当前cpu有partial链表,并且slub是full,那就将其移动进来;否则就是往node中移动的情况:
cross_cache
可以看到,如果我们存在一个double-free漏洞,将漏洞结构体释放两次,则可以让slab的inuse减少两次,那么就存在某一个同cache的结构体没有释放的情况下使inuse达到0,然后经过一系列的操作让这个slab被buddy-system回收,最终造成这个未释放结构体的cross-cache-uaf;