Linux内核中mod_timer与refcount_inc的并发安全性问题咨询
内核中mod_timer与refcount_inc的调用顺序安全性问题
我在内核代码中发现多处先调用mod_timer再调用refcount_inc的写法,示例代码如下:
static int ip_frag_reinit(struct ipq *qp) { unsigned int sum_truesize = 0; if (!mod_timer(&qp->q.timer, jiffies + qp->q.fqdir->timeout)) { refcount_inc(&qp->q.refcnt); return -ETIMEDOUT; } }
疑问点
定时器的回调逻辑大致如下:
void timer_callback() { ... refcount_dec(obj); }
当mod_timer返回时,定时器有可能已经在其他CPU上执行完毕。哪怕调用ip_frag_reinit的调用者已经持有该对象的引用,若定时器回调先执行,调用者侧的对象就会面临**UAF(释放后使用)**风险。另外内核中很多场景都采用相反的顺序:先调用refcount_inc再调用mod_timer,看起来这种顺序才是正确的。
结论:该调用顺序不安全
这种先mod_timer后refcount_inc的写法存在明确的UAF风险,具体分析如下:
1. 时序竞态导致的对象释放
mod_timer返回0时,表示定时器原本处于激活状态。此时原定时器的到期事件可能已经在其他CPU上触发,回调函数里的refcount_dec可能已经把对象的引用计数减至0,直接触发对象释放。而后续的refcount_inc操作的是已经被回收的内存,属于非法访问。
2. 引用计数的时机逻辑错误
调用者虽然持有对象引用,但定时器回调的执行时机不受当前上下文控制。如果在mod_timer之后才增加引用计数,无法保证在回调执行前完成计数保护——一旦回调先执行释放对象,调用者后续对该对象的所有操作都会变成UAF。
正确的调用方式
内核中普遍采用的**先refcount_inc再mod_timer**的顺序才是安全的:
- 提前增加引用计数,确保即使定时器回调立刻执行,
refcount_dec也不会将计数减到0,对象不会被释放。 - 引用计数操作在定时器修改前完成,从根源上避免了时序竞态引发的内存非法访问问题。
内容的提问来源于stack exchange,提问作者dsk
相关产品推荐
相关产品推荐

