Android内核漏洞学习——CVE-2014-3153分析(1)
字数 1995 2025-08-26 22:11:39
CVE-2014-3153 Android内核漏洞分析与利用教学文档
1. 漏洞概述
CVE-2014-3153是一个影响广泛的Linux内核提权漏洞,在Android系统中尤为著名。该漏洞由著名黑客Geohot利用并开发出TowelRoot工具,实现了简单粗暴的Android root提权。
漏洞本质是Linux内核中的use-after-free漏洞,涉及Futex(Fast Userspace muTexes)机制的实现问题。
2. Futex基础
2.1 Futex概念
Futex(快速用户空间互斥体)设计目的是加速glibc层的互斥访问速度,其核心思想是:
- 在用户空间检查竞争情况
- 无竞争时避免陷入内核,减少开销
- 必要时才进入内核处理
2.2 Futex系统调用
主要系统调用接口:
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
u32 __user *uaddr2, u32 val2, u32 val3)
操作类型(op)包括:
FUTEX_WAIT/FUTEX_WAKE:基本阻塞/唤醒操作FUTEX_LOCK_PI/FUTEX_UNLOCK_PI:优先级继承锁操作FUTEX_WAIT_REQUEUE_PI/FUTEX_CMP_REQUEUE_PI:涉及漏洞的关键操作
3. 漏洞成因分析
3.1 Relock问题
在futex_lock_pi_atomic函数中存在relock问题:
static int futex_lock_pi_atomic(u32 __user *uaddr, ...)
{
// 尝试获取锁:比较uaddr是否为0,若是则设置为TID
if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval)))
return -EFAULT;
// 如果获取成功(curval为0)
if (unlikely(!curval))
return 1;
...
}
问题:uaddr是用户空间变量,攻击者可手动设为0,绕过锁检查实现重复上锁,导致:
- 未调用
futex_unlock_pi释放锁就再次上锁 - 遗漏必要的收尾工作(如唤醒阻塞线程、修改pi_state等)
3.2 Requeue问题
涉及两个关键函数:
futex_wait_requeue_pi:在uaddr1上等待,准备被移动到uaddr2futex_requeue:唤醒uaddr1最高优先级线程,并将等待线程转移到uaddr2
问题调用序列:
futex_wait_requeue_pi(uaddr1, uaddr2)- 正常等待futex_requeue(uaddr1, uaddr2)- 正常唤醒,返回1(成功)futex_requeue(uaddr2, uaddr2)- 异常调用,返回0xffffffea(导致crash)
根本原因:内核未检查uaddr1和uaddr2是否相同,允许不合逻辑的自引用调用。
4. 漏洞利用原理
4.1 利用步骤
-
初始锁定:
- 线程1调用
futex_lock_pi(&B)成功锁定B,B值设为线程TID
- 线程1调用
-
等待requeue:
- 线程2调用
futex_wait_requeue_pi(&A, &B) - 初始化
futex_q和rt_mutex_waiter结构体 - 在A上等待,
futex_q加入A的PI chain
- 线程2调用
-
首次requeue尝试:
- 线程1调用
futex_requeue_pi(&A, &B) futex_proxy_trylock_atomic尝试获取B锁失败rt_mutex_start_proxy_lock也失败- 线程2阻塞在B的rt_mutex上,
rt_waiter加入waiter list
- 线程1调用
-
用户态解锁:
- 利用relock漏洞,用户态将B设为0
-
异常requeue调用:
- 调用
futex_requeue_pi(&B, &B) futex_proxy_trylock_atomic再次被调用- 因B=0,
futex_lock_pi_atomic成功获取锁 requeue_pi_wake_futex唤醒线程2q->rt_waiter被置NULL
- 调用
-
UAF触发:
futex_wait_requeue_pi认为未进入内核等待- 未清理
rt_waiter(实际已在栈上) - 线程结束后回收等待链表,引用未清理的
rt_waiter导致use-after-free
4.2 关键数据结构
futex_q:表示一个futex等待队列项rt_mutex_waiter:实时互斥锁的等待者结构pi_state:优先级继承状态
5. 漏洞利用代码分析
典型利用模式伪代码:
// 线程1
futex_lock_pi(&B); // 锁定B
// 线程2
futex_wait_requeue_pi(&A, &B); // 在A上等待被移动到B
// 线程1
futex_requeue_pi(&A, &B); // 尝试将线程2从A移动到B
*(int*)&B = 0; // 用户态解锁B
futex_requeue_pi(&B, &B); // 触发漏洞的关键调用
// 此时已造成rt_waiter的UAF条件
6. 防护与修复
修复措施包括:
- 添加uaddr1和uaddr2相同性检查
- 完善锁状态管理,防止relock
- 加强
rt_waiter生命周期管理
7. 参考资源
- Linux内核源码:
kernel/futex.c - 《漏洞战争》CVE-2014-3153章节
- 相关技术博客分析文章
8. 教学实验建议
实验环境搭建:
- 受影响内核版本(如Linux 3.4)
- QEMU模拟环境
- 配套的漏洞利用代码
实验步骤:
- 复现基本崩溃
- 分析崩溃时的内核状态
- 构造完整提权利用
- 验证修复方案的有效性
注意:本漏洞涉及内核关键数据结构操作,实验需在可控环境中进行,避免影响生产系统。