Bug 453419 (CVE-2008-2812) - CVE-2008-2812 kernel: NULL ptr dereference in multiple network drivers due to missing checks in tty code
Summary: CVE-2008-2812 kernel: NULL ptr dereference in multiple network drivers due to...
Keywords:
Status: CLOSED ERRATA
Alias: CVE-2008-2812
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
Depends On: 453154 453155 453158 453423 453425
Blocks:
TreeView+ depends on / blocked
 
Reported: 2008-06-30 14:57 UTC by Eugene Teo (Security Response)
Modified: 2019-09-29 12:25 UTC (History)
5 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2010-12-23 21:09:39 UTC
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2008:0612 0 normal SHIPPED_LIVE Important: kernel security and bug fix update 2008-08-06 14:46:27 UTC
Red Hat Product Errata RHSA-2008:0665 0 normal SHIPPED_LIVE Moderate: Updated kernel packages for Red Hat Enterprise Linux 4.7 2008-07-24 16:41:06 UTC
Red Hat Product Errata RHSA-2008:0973 0 normal SHIPPED_LIVE Important: kernel security and bug fix update 2008-12-17 03:18:50 UTC

Description Eugene Teo (Security Response) 2008-06-30 14:57:34 UTC
Alan Cox discovered that users or admins can get the kernel to execute through
a NULL pointer due to missing checks in the tty code.

Comment 1 Eugene Teo (Security Response) 2008-06-30 15:02:32 UTC
Proposed patch from Alan:

diff -u --new-file --recursive a/drivers/net/hamradio/6pack.c
b/drivers/net/hamradio/6pack.c
--- a/drivers/net/hamradio/6pack.c	2008-06-25 16:52:02.000000000 +0100
+++ b/drivers/net/hamradio/6pack.c	2008-06-27 12:05:05.000000000 +0100
@@ -601,6 +601,8 @@
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
+	if (!tty->driver->write)
+		return -EOPNOTSUPP;
 
 	dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
 	if (!dev) {
diff -u --new-file --recursive a/drivers/net/hamradio/mkiss.c
b/drivers/net/hamradio/mkiss.c
--- a/drivers/net/hamradio/mkiss.c	2008-06-25 16:52:02.000000000 +0100
+++ b/drivers/net/hamradio/mkiss.c	2008-06-27 12:06:51.000000000 +0100
@@ -530,6 +530,7 @@
 static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct mkiss *ax = netdev_priv(dev);
+	int cib = 0;
 
 	if (!netif_running(dev))  {
 		printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
@@ -545,10 +546,11 @@
 			/* 20 sec timeout not reached */
 			return 1;
 		}
+		if (ax->tty->drivers->chars_in_buffer)
+			cib = ax->tty->chars_in_buffer(ax->tty);
 
 		printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
-		       (ax->tty->driver->chars_in_buffer(ax->tty) || ax->xleft) ?
-		       "bad line quality" : "driver error");
+		     cib || ax->xleft) ? "bad line quality" : "driver error");
 
 		ax->xleft = 0;
 		clear_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
@@ -736,6 +738,8 @@
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
+	if (!tty->driver->write)
+		return -EOPNOTSUPP;
 
 	dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
 	if (!dev) {
diff -u --new-file --recursive a/drivers/net/irda/irtty-sir.c
b/drivers/net/irda/irtty-sir.c
--- a/drivers/net/irda/irtty-sir.c	2008-06-25 16:52:02.000000000 +0100
+++ b/drivers/net/irda/irtty-sir.c	2008-06-27 12:09:29.000000000 +0100
@@ -64,7 +64,9 @@
 	IRDA_ASSERT(priv != NULL, return -1;);
 	IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
 
-	return priv->tty->driver->chars_in_buffer(priv->tty);
+	if (priv->tty->drivers->chars_in_buffer)
+		return priv->tty->driver->chars_in_buffer(priv->tty);
+	return 0;
 }
 
 /* Wait (sleep) until underlaying hardware finished transmission
diff -u --new-file --recursive a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
--- a/drivers/net/ppp_async.c	2008-06-25 16:52:00.000000000 +0100
+++ b/drivers/net/ppp_async.c	2008-06-27 12:04:08.000000000 +0100
@@ -157,6 +157,9 @@
 {
 	struct asyncppp *ap;
 	int err;
+	
+	if (!tty->driver->write)
+		return -EOPNOTSUPP;
 
 	err = -ENOMEM;
 	ap = kmalloc(sizeof(*ap), GFP_KERNEL);
diff -u --new-file --recursive a/drivers/net/ppp_synctty.c
b/drivers/net/ppp_synctty.c
--- a/drivers/net/ppp_synctty.c	2008-06-25 16:52:00.000000000 +0100
+++ b/drivers/net/ppp_synctty.c	2008-06-27 12:04:22.000000000 +0100
@@ -207,6 +207,9 @@
 	struct syncppp *ap;
 	int err;
 
+	if (!tty->driver->write)
+		return -EOPNOTSUPP;
+
 	ap = kmalloc(sizeof(*ap), GFP_KERNEL);
 	err = -ENOMEM;
 	if (ap == 0)
diff -u --new-file --recursive a/drivers/net/slip.c b/drivers/net/slip.c
--- a/drivers/net/slip.c	2008-06-25 16:52:02.000000000 +0100
+++ b/drivers/net/slip.c	2008-06-27 12:03:40.000000000 +0100
@@ -463,9 +463,14 @@
 			/* 20 sec timeout not reached */
 			goto out;
 		}
-		printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
-		       (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
-		       "bad line quality" : "driver error");
+		{
+			int cib = 0;
+			if (sl->tty->driver->chars_in_buffer)
+				cib = sl->tty->driver->chars_in_buffer(sl->tty);
+			printk(KERN_WARNING "%s: transmit timed out, %s?\n",
+				dev->name, (cib || sl->xleft) ?
+				       "bad line quality" : "driver error");
+		}	
 		sl->xleft = 0;
 		sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 		sl_unlock(sl);
@@ -836,7 +841,9 @@
 
 	if(!capable(CAP_NET_ADMIN))
 		return -EPERM;
-		
+	if (!tty->driver->write)
+		return -EOPNOTSUPP;
+		
 	/* RTnetlink lock is misused here to serialize concurrent
 	   opens of slip channels. There are better ways, but it is
 	   the simplest one.
diff -u --new-file --recursive a/drivers/net/wan/x25_asy.c
b/drivers/net/wan/x25_asy.c
--- a/drivers/net/wan/x25_asy.c	2008-06-25 16:52:01.000000000 +0100
+++ b/drivers/net/wan/x25_asy.c	2008-06-27 12:08:53.000000000 +0100
@@ -283,6 +283,10 @@
 static void x25_asy_timeout(struct net_device *dev)
 {
 	struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+	int cib = 0;
+
+	if (sl->tty->driver->chars_in_buffer)
+		cib = sl->tty->driver->chars_in_buffer(sl->tty);
 
 	spin_lock(&sl->lock);
 	if (netif_queue_stopped(dev)) {
@@ -290,8 +294,7 @@
 		 *      14 Oct 1994 Dmitry Gorodchanin.
 		 */
 		printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
-		       (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
-		       "bad line quality" : "driver error");
+		       (cib || sl->xleft) ? "bad line quality" : "driver error");
 		sl->xleft = 0;
 		sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 		x25_asy_unlock(sl);
@@ -561,6 +564,9 @@
 		return -EEXIST;
 	}
 
+	if (!tty->driver->write)
+		return -EOPNOTSUPP;
+
 	/* OK.  Find a free X.25 channel to use. */
 	if ((sl = x25_asy_alloc()) == NULL) {
 		return -ENFILE;
diff -u --new-file --recursive a/drivers/net/wireless/strip.c
b/drivers/net/wireless/strip.c
--- a/drivers/net/wireless/strip.c	2008-06-25 16:52:01.000000000 +0100
+++ b/drivers/net/wireless/strip.c	2008-06-27 12:01:04.000000000 +0100
@@ -801,7 +801,8 @@
 	struct termios old_termios = *(tty->termios);
 	tty->termios->c_cflag &= ~CBAUD;	/* Clear the old baud setting */
 	tty->termios->c_cflag |= baudcode;	/* Set the new baud setting */
-	tty->driver->set_termios(tty, &old_termios);
+	if (tty->driver->set_termios)
+		tty->driver->set_termios(tty, &old_termios);
 }
 
 /*

Comment 6 Eugene Teo (Security Response) 2008-07-01 03:41:27 UTC
Proposed upstream patch for the rest of the fixes:

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=f34d7a5b7010b82fe97da95496b9971435530062

Comment 12 Vincent Danen 2010-12-23 21:09:39 UTC
This was addressed via:

Red Hat Enterprise Linux version 5 (RHSA-2008:0612)
Red Hat Enterprise Linux version 4 (RHSA-2008:0665)
Red Hat Enterprise Linux version 3 (RHSA-2008:0973)


Note You need to log in before you can comment on or make changes to this bug.