Linux kernel /dev/net/tun NULL Pointer Dereference
This is a really cool vulnerability which was reported with a trigger code from Eugene Kapun. It affects Linux kernel 2.6.30 and it can be found in drivers/net/tun.c like that.
/* Poll */
static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun = __tun_get(tfile);
struct sock *sk = tun->sk;
unsigned int mask = 0;
if (!tun)
return POLLERR;
DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
poll_wait(file, &tun->socket.wait, wait);
if (!skb_queue_empty(&tun->readq))
mask |= POLLIN | POLLRDNORM;
if (sock_writeable(sk) ||
(!test_and_set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
sock_writeable(sk)))
mask |= POLLOUT | POLLWRNORM;
if (tun->dev->reg_state != NETREG_REGISTERED)
mask = POLLERR;
tun_put(tun);
return mask;
}
The bug is quite obvious. It initializes sk to tun->sk and THEN it checks if tun is NULL :P Of course, this should be done first since the compiler will optimize it and completely remove the if(!tun) check since it is performed after the assignment. Because of this, the above vulnerability can result in a nice exploitable NULL pointer dereference. This was fixed by updating the code like that:
- struct sock *sk = tun->sk; + struct sock *sk; unsigned int mask = 0; if (!tun) return POLLERR; + sk = tun->sk; + DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
P.S.: spender, ok… I will post similar bugs in the future :P

xorl,
Where is your original post on this “silent fix” that spender refers to in his comments? I couldn’t find it here on the blog, though honestly I’m not quite sure what I’m looking for.
Thanks,
–Mish
Mish
July 17, 2009 at 14:19
Mish, I haven’t posted anything before for that particular bug. I believe spender was referring in general to the silently fixed vulnerabilities in the Linux kernel.
xorl
July 17, 2009 at 15:40
Mish: xorl is right, I just was asking him in my exploit to report more on silently fixed vulnerabilities in the Linux kernel in general :)
Bradley Spengler
July 18, 2009 at 00:10
/dev/net/tun is rw only for root in most distributions. I’m missing something here.
Alfred
July 22, 2009 at 15:29
@Alfred: This question has already been answered by spender (the author of the Cheddar Bay exploit) and you can read it here:
http://xorl.wordpress.com/2009/07/18/linux-kernel-nvram-integer-overflow/#comment-300
Hope this helps. :)
xorl
July 22, 2009 at 15:36
Ahh I knew it!! :)
Thanks Xorl
Alfred
July 22, 2009 at 15:48