理解竞争条件( Race condition)漏洞
这几天一个叫做"Dirty COW"的linux内核竞争条件漏洞蛮火的,相关公司不但给这个漏洞起了个洋气的名字,还给它设计了logo(见下图),首页,Twitter账号以及网店。恰逢周末,闲来无事的我也强势围观了一波,在这之前,好好的学习了一下竞争条件以及看了一下近几年关于竞争条件漏洞。

1:什么是竞争条件以及竞争条件为什么会产生漏洞
竞争条件是系统中的一种反常现象,由于现代Linux系统中大量使用并发编程,对资源进行共享,如果产生错误的访问模式,便可能产生内存泄露,系统崩溃,数据破坏,甚至安全问题。竞争条件漏洞就是多个进程访问同一资源时产生的时间或者序列的冲突,并利用这个冲突来对系统进行攻击。一个看起来无害的程序如果被恶意攻击者利用,将发生竞争条件漏洞。
用简单代码讲的更清楚:
//myThreadTest
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> int i = ;
void *mythread1()
{
if(i == ){ <a>
sleep();
if(i == ) <b>
printf("hack it!\n"); else
printf("you can try again!\n");
}
}
void *mythread2()
{
sleep();
i=;
} int main(int argc, const char *argv[])
{
pthread_t id1,id2; pthread_create(&id1, NULL, (void *)mythread1,NULL);
pthread_create(&id2, NULL, (void *)mythread2,NULL); pthread_join(id1,NULL);
pthread_join(id2,NULL); return ;
}
单独看mythread1()函数,显然肯定是输出 "you can try again!\n",但是,由于i是全局共享的资源可以通过线程的方式来使i值在<a>的之后<b>之前进行改变,可以改变函数的流程

为了使结果清晰明了,所以手动利用sleep()函数进行设置了,实际利用过程中,可能是一些会耗时较长的函数,如memcpy()
流程如下:

这也是竞争条件的核心思想,这也是一个数据竞争引发条件竞争的典型例子。
2:以cve-2014-0496为例
由于Android的崛起起,Linux内核的安全性受到了极大地考验,很多潜藏的安全也慢慢被安全研究眼发现。这个漏洞的主要成因是因为在pty/tty设备驱动中在访问某些资源的时候没有正确的加锁处理,准确来说,加锁的范围较小。首先,先看一下理解这个漏洞必要的两个数据结构
struct tty_buffer {
struct tty_buffer *next;
char *char_buf_ptr;
unsigned char *flag_buf_ptr;
int used;
int size;
int commit;
int read;
/* Data points here */
unsigned long data[];
};
struct tty_struct {
int magic;
struct kref kref;
struct device *dev;
struct tty_driver *driver;
const struct tty_operations *ops;
struct tty_bufhead buf;
};
tty_buffer是一个动态大小的数据结构,其中,char_buf_ptr指向该对象后面的第一字节,即(char_buf_ptr = tty_buffer+sizeof(tty_buffer)大小为size... flag_buf_ptr=tty_buffer+sizeof(tty_buffer)+size。大小为size。used为已经使用的buffer大小。tty_struct为tty的数据结构,其中ops为tty设备的一些操作函数,如open(),write()。
该漏洞的函数调用为write(pty_fd) in userspace -> sys_write() in kernelspace -> tty_write() -> pty_write() -> tty_insert_flip_string_fixed_flag()。看 tty_insert_flip_string_fixed_flag()函数:
int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
const unsigned char *chars, char flag, size_t size)
{
int copied = ;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
int space = tty_buffer_request_room(tty, goal);
struct tty_buffer *tb = tty->buf.tail;
if (unlikely(space == ))
break;
memcpy(tb->char_buf_ptr + tb->used, chars, space);
memset(tb->flag_buf_ptr + tb->used, flag, space);
tb->used += space;
copied += space;
chars += space;
} while (unlikely(size > copied));
return copied;
}
这个函数的大致流程为通过tty_buffer_request_room来申请函数空间,如果没有,则另外申请。利用memcpy进行复制内存。最后再递增used。其中memcpy调用时间较长,由于没有加锁,存在竞争条件的问题,查看tty_buffer_request_room,看是否能够利用:
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
struct tty_buffer *b, *n;
int left;
unsigned long flags; spin_lock_irqsave(&tty->buf.lock, flags); if ((b = tty->buf.tail) != NULL)
left = b->size - b->used;
else
left = 0;
if (left < size) { <1>
/* This is the slow path - looking for new buffers to use */
if ((n = tty_buffer_find(tty, size)) != NULL) {
if (b != NULL) {
b->next = n;
b->commit = b->used;
} else
tty->buf.head = n;
tty->buf.tail = n;
} else
size = left;
}
spin_unlock_irqrestore(&tty->buf.lock, flags);
return size;
}
这里有一个整数溢出的问题,由于程序员的疏忽size为unsigned,而left为int,根据c语言规则,left为转化为无符号,在<1>中,如果left为负数,转化为无符号数,便可以实现size大于left,即需要的空间大于空余的空间,但是仍不进行内存分配,再通过tty_insert_flip_string_fixed_flag函数里的memcpy来溢出,对内存进行读写。left = b->size - b->used,其中size不能改变,但是可以改变used的值,通过条件竞争,来对used进行连续多次写,使used大于size。
详细流程图如下:

由于memcpy函数将会持续较长时间,只要对一个tty连续多次利用多线程对该函数进行申请空间,使used > size,这样就可以在使用memcpy时,进行内存溢出。
这个漏洞,是一个非常典型的竞争条件漏洞。其实也就是上面那个测试代码也是这个函数的简化版。
3:结语
在现代操作系统,竞争条件是不可避免的,只要两个两个执行线程访问同一个数据结构,由于我们无法预测linux调度的顺序,就会产生混合,就可能产竞争条件。我们如果需要对内核或驱动编写,应该尽量避免资源的共享,如果不可避免,需要利用锁来对原子数据进行锁定。
理解竞争条件( Race condition)漏洞的更多相关文章
- 竞态条件 race condition data race
竞态条件 race condition Race condition - Wikipedia https://en.wikipedia.org/wiki/Race_condition A race c ...
- Golang 入门 : 竞争条件
笔者在前文<Golang 入门 : 理解并发与并行>和<Golang 入门 : goroutine(协程)>中介绍了 Golang 对并发的原生支持以及 goroutine 的 ...
- Fortify Audit Workbench 笔记 Race Condition: Singleton Member Field 竞争条件:单例的成员字段
Race Condition: Singleton Member Field 竞争条件:单例的成员字段 Abstract Servlet 成员字段可能允许一个用户查看其他用户的数据. Explanat ...
- Operating System-进程/线程内部通信-竞争条件(Race Conditions)
从本文开始介绍进程间的通信,进程间通信遇到的问题以及方式其实和线程之间通信是一致的,所以进程间通信的所有理论知识都可以用在线程上,接下来的系列文章都会以进程之间的通信为模版进行介绍,本文主要内容: 进 ...
- WEB安全新玩法 [10] 防范竞争条件支付漏洞
服务器端业务逻辑,特别是涉及数据库读写时,存在着关键步骤的时序问题,如果设计或代码编写不当就可能存在竞争条件漏洞.攻击者可以利用多线程并发技术,在数据库的余额字段更新之前,同时发起多次兑换积分或购买商 ...
- 理解 Linux 条件变量
理解 Linux 条件变量 1 简介 当多个线程之间因为存在某种依赖关系,导致只有当某个条件存在时,才可以执行某个线程,此时条件变量(pthread_cond_t)可以派上用场.比如: 例1: 当系统 ...
- Race condition
在很多门课上都接触到race condition, 其中也举了很多方法解决这个问题.于是想来总结一下这些方法. Race condition 它旨在描述一个系统或者进程的输出依赖于不受控制的事件出现顺 ...
- 【多线程同步案例】Race Condition引起的性能问题
Race Condition(也叫做资源竞争),是多线程编程中比较头疼的问题.特别是Java多线程模型当中,经常会因为多个线程同时访问相同的共享数据,而造成数据的不一致性.为了解决这个问题,通常来说需 ...
- python线程条件变量Condition(31)
对于线程与线程之间的交互我们在前面的文章已经介绍了 python 互斥锁Lock / python事件Event , 今天继续介绍一种线程交互方式 – 线程条件变量Condition. 一.线程条件变 ...
随机推荐
- centos6安装openfire(mysql)
一.安装JDK 我的系统是centos6.8x64,首先安装jdk1.7.0 二.安装openfire 我装的包是:openfire-3.9.3-1.i386.rpm,复制到/opt目录 #rpm - ...
- Codeforces 1088E 树形dp+思维
比赛的时候看到题意没多想就放弃了.结果最后D也没做出来,还掉分了,所以还是题目做的太少,人太菜. 回到正题: 题意:一棵树,点带权值,然后求k个子连通块,使得k个连通块内所有的点权值相加作为分子除以k ...
- 通过nbviwer在线分享python notebook
在数据科学计算中,jupyter-notebook是一个很得力的助手,但是Notebook写完之后如何与他人分享呢?我们可以使用nbviwer. 具体思路: 具体的方法如下: 本地编写ipython ...
- 团队冲刺Alpha(六)
目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示 ...
- BZOJ1565 [NOI2009]植物大战僵尸 【最大权闭合子图 + tarjan缩点(或拓扑)】
题目 输入格式 输出格式 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. 输入样例 3 2 10 0 20 0 -10 0 -5 1 0 0 100 ...
- 【CZY选讲·一道图论神题】
题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图,只有点权. LYK想把这个图删干净,它的方法是这样的.每次选择一个点,将它删掉,但删这个点是需要代价的 ...
- OpenNI2安装
1.Openni2:从官网下载linux用zip压缩包,解压再解压2.终端转到解压目录下,找到install.sh文件,执行$sudo ./install.sh 3.执行后,生成OpenNIDevEn ...
- poj 2367 拓扑排序入门
Description The system of Martians' blood relations is confusing enough. Actually, Martians bud when ...
- ASP.NET Identity 使用 RoleManager 进行角色管理 (VS2013RC)
注:本文系作者原创,但可随意转载. 最近做一个Web平台系统,系统包含3个角色,“管理员, 企业用户, 评审专家”, 分别有不同的功能.一直以来都是使用微软封装好的Microsoft.AspNet.I ...
- 7月10日day2总结
今天学习过程和小结 上午: java项目建立方法,maven Tomcat的部署和MySQL的安装与权限. 分配时中datanote和namenote DataNode 作用 1Data Node以数 ...