Bug 453419 (CVE-2008-2812)
| Summary: | CVE-2008-2812 kernel: NULL ptr dereference in multiple network drivers due to missing checks in tty code | ||
|---|---|---|---|
| Product: | [Other] Security Response | Reporter: | Eugene Teo (Security Response) <eteo> |
| Component: | vulnerability | Assignee: | Red Hat Product Security <security-response-team> |
| Status: | CLOSED ERRATA | QA Contact: | |
| Severity: | medium | Docs Contact: | |
| Priority: | medium | ||
| Version: | unspecified | CC: | anton, dhoward, lwang, skakar, vgoyal |
| Target Milestone: | --- | Keywords: | Security |
| Target Release: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | Bug Fix | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2010-12-23 21:09:39 UTC | Type: | --- |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | 453154, 453155, 453158, 453423, 453425 | ||
| Bug Blocks: | |||
|
Description
Eugene Teo (Security Response)
2008-06-30 14:57:34 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);
}
/*
Proposed upstream strip driver commit from Alan: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blobdiff;f=drivers/net/wireless/strip.c;h=883af891ebfb4c54d19daff25495af0a063734f4;hp=5dd23c93497db90163365b84a7e62917571cd122;hb=79f999d0aa264f72f5491be14b4bf60137a3d3a9;hpb=492c2e476eac010962850006c49df326919b284c 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 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) |