简介
2020年10月公布了bulletin,这是最近新的提权漏洞,存在于binder中。
这个漏洞大致上是binder的sender和receive端的对binder_node结构体的race condition转化为uaf漏洞,作者进一步触发了double free,结合后续巧妙的堆喷分配,利用slub和ksma机制,绕过kalsr和cfi保护,官方给出影响的版本在Android 8-11之间,详细的英文文章请参考这里https://blog.longterm.io/cve-2020-0423.html
poc的触发
其poc触发形式为:
Thread 1: enter binder_release_work from binder_thread_release
Thread 2: binder_update_ref_for_handle() -> binder_dec_node_ilocked()
Thread 2: dec nodeA --> 0 (will free node)
Thread 1: ACQ inner_proc_lock
Thread 2: block on inner_proc_lock
Thread 1: dequeue work (BINDER_WORK_NODE, part of nodeA)
Thread 1: REL inner_proc_lock
Thread 2: ACQ inner_proc_lock
Thread 2: todo list cleanup, but work was already dequeued
Thread 2: free node
Thread 2: REL inner_proc_lock
Thread 1: deref w->type (UAF)
分开来看的话,
Thread 1: enter binder_release_work from binder_thread_release
Thread 1: ACQ inner_proc_lock 获取锁
Thread 1: dequeue work (BINDER_WORK_NODE, part of nodeA) 从链表中摘除binder_work
Thread 1: REL inner_proc_lock 释放锁
Thread 1: deref w->type (UAF) 引用binder_work->type
再来看Thread 2
Thread 2: binder_update_ref_for_handle() -> binder_dec_node_ilocked()
Thread 2: dec nodeA --> 0 (will free node)
Thread 2: block on inner_proc_lock 等待锁被thread释放
Thread 2: ACQ inner_proc_lock 获取锁
Thread 2: todo list cleanup, but work was already dequeued 清空链表
Thread 2: free node 释放binder_node
Thread 2: REL inner_proc_lock 释放锁
可以看到binder_work拿到之后, 但是另一个线程紧接这free掉了它,但后续还直接使用它,造成了uaf。
binder_work又是binder_node的成员
patch前后
通过patch前后的对比,主要增大了binder_inner_proc_lock(proc);锁的范围。所以这个漏洞也可以说是开发时没有考虑到锁的范围导致的。
poc可以分为三个阶段触发:
生成一个transaction来触发bug
发送BINDER_THREAD_EXIT
多线程来竞争
在步骤1中必须包含BINDER_TYPE_BINDER 或者