上一篇博客我们简单了解了CVE-2016-7637,简单了解了mach ipc在通讯的过程中遇到的一些问题,这次我们来看有关mach ipc的第二个漏洞cve-2016-7644
基本概念
同步机制
前面几篇文章都介绍了Mach IPC的一些关于message
的知识,实际上在Mach IPC中,不光有消息传递机制,还有一个同步机制
,主要判定两个或者多个并发的操作如何访问共享的资源。
Mach的同步机制中有4个对象,最基本的就是互斥体,当别人使用资源时可以排除其他人对这个资源的访问。但是有一个特殊的要求:硬件对互斥体的进行原子操作
,就是即使硬件中断也不打断互斥体的操作。
对象 | 所有者 | 可见性 | 等待 |
---|---|---|---|
互斥体 | 1个 | 内核态 | 阻塞 |
信号量 | 多个 | 用户态 | 阻塞 |
自旋锁 | 1个 | 内核态 | 忙等 |
锁集 | 1个 | 用户态 | 阻塞 |
说到这里就要介绍一下锁组
大部分Mach同步对象并不是独立存在的,而是属于一个
lck_grp_t
(锁组) 对象。
在Mach和BSD中几乎每一个子系统在初始化时都会创建一个锁组
由上表可知互斥体和信号量都是阻塞等待的对象,阻塞等待就是如果锁的对象被其他线程所占有,那么请求访问的线程就会被加入到等待队列中,从而被阻塞。
接下来这个漏洞就是由于没有引入锁组
机制形成条件竞争导致内核UAF
cve-2016-7644
这个漏洞是在调用set_dp_control_port
函数时,由于没有锁组
机制,造成了当两个线程同时调用时,会释放port的两个reference
,调用两次ipc_port_release_send
函数。
漏洞源码在vm_user.c中,
这个漏洞也比较简单,但由此也简单接触了另一个Mach IPC的机制同步机制
,至于poc的分析我们将在最后一篇文章中一起介绍
Ian beer关于漏洞的write up
在这里
接下来我们来简单分析一下ian beer的利用代码(kernel_sploit.c文件中)
以上代码中,我们共拥有三组port的right和reference
- 通过mach_port_allocate函数拥有right和reference
- 通过stash_port,当stash_port没有free时,在ipc中存了一份right和reference
- 通过set_dp_control_port函数拥有right和reference
|
|
通过mach_port_deallocate,使得right为2,reference为3
当两个线程并发执行时,就会调用两次ipc_port_release_send函数,每执行一次这个函数,port的reference就减少一。这样release两次之后,right为0,reference为1。
“由于没有send right,所以会产生一个notify,这也是一个出发了这个条件竞争漏洞的标志”