BUGTRAQ ID: 37147 Linux Kernel是开放源码操作系统Linux所使用的内核。 Linux Kernel所使用的drivers/char/n_tty.c驱动中存在空指针引用漏洞: /** * n_tty_close - close the ldisc for this tty * @tty: device * * Called from the terminal layer when this line discipline is * being shut down, either because of a close or becsuse of a * discipline change. The function will not be called while other * ldisc methods are in progress. */ static void n_tty_close(struct tty_struct *tty) { n_tty_flush_buffer(tty); if (tty->read_buf) { kfree(tty->read_buf); tty->read_buf = NULL; } if (tty->echo_buf) { kfree(tty->echo_buf); tty->echo_buf = NULL; } } 这个例程的参数是以指向tty_struct结构的指针形式传送的TTY,首先调用n_tty_flush_buffer()然后释放所分配的read_buf和echo_buf缓冲区,并将其设置为NULL。在这里所调用的第一个函数为: /** * n_tty_flush_buffer - clean input queue * @tty: terminal device * * Flush the input buffer. Called when the line discipline is * being closed, when the tty layer wants the buffer flushed (eg * at hangup) or when the N_TTY line discipline internally has to...
BUGTRAQ ID: 37147 Linux Kernel是开放源码操作系统Linux所使用的内核。 Linux Kernel所使用的drivers/char/n_tty.c驱动中存在空指针引用漏洞: /** * n_tty_close - close the ldisc for this tty * @tty: device * * Called from the terminal layer when this line discipline is * being shut down, either because of a close or becsuse of a * discipline change. The function will not be called while other * ldisc methods are in progress. */ static void n_tty_close(struct tty_struct *tty) { n_tty_flush_buffer(tty); if (tty->read_buf) { kfree(tty->read_buf); tty->read_buf = NULL; } if (tty->echo_buf) { kfree(tty->echo_buf); tty->echo_buf = NULL; } } 这个例程的参数是以指向tty_struct结构的指针形式传送的TTY,首先调用n_tty_flush_buffer()然后释放所分配的read_buf和echo_buf缓冲区,并将其设置为NULL。在这里所调用的第一个函数为: /** * n_tty_flush_buffer - clean input queue * @tty: terminal device * * Flush the input buffer. Called when the line discipline is * being closed, when the tty layer wants the buffer flushed (eg * at hangup) or when the N_TTY line discipline internally has to * clean the pending queue (for example some signals). * * Locking: ctrl_lock, read_lock. */ static void n_tty_flush_buffer(struct tty_struct *tty) { unsigned long flags; /* clear everything and unthrottle the driver */ reset_buffer_flags(tty); if (!tty->link) return; spin_lock_irqsave(&tty->ctrl_lock, flags); if (tty->link->packet) { tty->ctrl_status |= TIOCPKT_FLUSHREAD; wake_up_interruptible(&tty->link->read_wait); } spin_unlock_irqrestore(&tty->ctrl_lock, flags); } 上面所保持的唯一一个锁是n_tty_flush_buffer()中的自旋锁。由于这个过程中没有其他的锁,这可能导致竞争条件。具体来讲,在释放缓冲区和kfree()指针期间n_tty_close()没有锁定,如果TTY接收到了字符,代码执行就会到达以下函数: static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) { unsigned long flags; int parmrk; if (tty->raw) { put_tty_queue(c, tty); return; } ... put_tty_queue(c, tty); } 结果会是: static void put_tty_queue(unsigned char c, struct tty_struct *tty) { unsigned long flags; /* * The problem of stomping on the buffers ends here. * Why didn't anyone see this one coming? --AJK */ spin_lock_irqsave(&tty->read_lock, flags); put_tty_queue_nolock(c, tty); spin_unlock_irqrestore(&tty->read_lock, flags); } 这会锁定TTY并调用执行以下内容的相应非锁定例程: static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty) { if (tty->read_cnt < N_TTY_BUF_SIZE) { tty->read_buf[tty->read_head] = c; tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1); tty->read_cnt++; } } 由于这时tty->read_buf可能已被释放并在n_tty_close()中设置为NULL,分配新的字符“c”可能导致试图访问并写入空指针,之后触发空指针引用。 Linux kernel 2.6.31.5 厂商补丁: Linux ----- 目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本: http://www.kernel.org/