From: Neil Horman <nhorman@redhat.com> Date: Wed, 20 Jan 2010 13:01:17 -0500 Subject: [net] r8169: improved frame length filtering Message-id: 20100120180117.GC6313@hmsreliant.think-freely.org O-Subject: [kernel team] [RHEL 5.3z PATCH] r8169: fix overlength check (bz 550913) Bugzilla: 550913 CVE: CVE-2009-4537 5.3.z backport of r8169 overlength check fix fixes bz 550913 diff -up linux-2.6.18.noarch/drivers/net/r8169_compat.h.orig linux-2.6.18.noarch/drivers/net/r8169_compat.h --- linux-2.6.18.noarch/drivers/net/r8169_compat.h.orig 2010-01-20 12:13:40.000000000 -0500 +++ linux-2.6.18.noarch/drivers/net/r8169_compat.h 2010-01-20 13:00:48.000000000 -0500 @@ -56,5 +56,6 @@ static inline int backport_schedule_dela #define schedule_delayed_work backport_schedule_delayed_work +#define ETH_FCS_LEN 4 #endif diff -up linux-2.6.18.noarch/drivers/net/r8169.c.orig linux-2.6.18.noarch/drivers/net/r8169.c --- linux-2.6.18.noarch/drivers/net/r8169.c.orig 2010-01-20 12:13:51.000000000 -0500 +++ linux-2.6.18.noarch/drivers/net/r8169.c 2010-01-20 13:00:48.000000000 -0500 @@ -182,7 +182,12 @@ static struct pci_device_id rtl8169_pci_ MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); -static int rx_copybreak = 200; +/* + * we set our copybreak very high so that we don't have + * to allocate 16k frames all the time (see note in + * rtl8169_open() + */ +static int rx_copybreak = 16383; static int use_dac; static struct { u32 msg_enable; @@ -2183,11 +2188,15 @@ static void __devexit rtl8169_remove_one } static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, - struct net_device *dev) + unsigned int mtu) { - unsigned int mtu = dev->mtu; + unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; + + if (max_frame != 16383) + printk(KERN_WARNING "WARNING! Changing of MTU on this NIC" + "May lead to frame reception errors!\n"); - tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE; + tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; } static int rtl8169_open(struct net_device *dev) @@ -2197,7 +2206,17 @@ static int rtl8169_open(struct net_devic int retval = -ENOMEM; - rtl8169_set_rxbufsize(tp, dev); + /* + * Note that we use a magic value here, its wierd I know + * its done because, some subset of rtl8169 hardware suffers from + * a problem in which frames received that are longer than + * the size set in RxMaxSize register return garbage sizes + * when received. To avoid this we need to turn off filtering, + * which is done by setting a value of 16383 in the RxMaxSize register + * and allocating 16k frames to handle the largest possible rx value + * thats what the magic math below does. + */ + rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN); /* * Rx and Tx desscriptors needs 256 bytes alignment. @@ -2852,7 +2871,7 @@ static int rtl8169_change_mtu(struct net rtl8169_down(dev); - rtl8169_set_rxbufsize(tp, dev); + rtl8169_set_rxbufsize(tp, dev->mtu); ret = rtl8169_init_ring(dev); if (ret < 0)