0x0 漏洞信息
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-0196
0x1 漏洞描述
n_tty_write函数没有加锁,导致同步状态下出现条件竞争的漏洞.
0x2 代码分析
先看tty_buffer
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[0];
};
这个结构后面会直接跟着char_buffer和flag_buffer,这两个缓冲区的大小都是size
size 开始的时候会是256 ,最大可以分配到TTY_BUFFER_PAGE
#define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF)</span>
问题具体发生在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 = 0;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
//使用tty_buffer_request_room判断是否内存是否足够,如果没有则申请更大内存
int space = tty_buffer_request_room(tty, goal);
struct tty_buffer *tb = tty->buf.tail;
if (unlikely(space == 0))
break;
//拷贝应用层传递下来的内容到buffer中
memcpy(tb->char_buf_ptr + tb->used, chars, space);
memset(tb->flag_buf_ptr + tb->used, flag, space);
//增加tb->used
tb->used += space;
copied += space;
chars += space;
/* There is a small chance that we need to split the data over
several buffers. If this is the case we must loop */
} while (unlikely(size > copied));
return copied;
}
再看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);
/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
remove this conditional if its worth it. This would be invisible
to the callers */