aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Horman <nhorman@redhat.com>2010-03-29 16:16:02 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-04-01 19:02:10 -0400
commit8c96206544955131f6d7cef09371950f34ebca5a (patch)
tree12a6ef8e9cacb665f13289f573535667eb9dbbe8
parentf8adc4007d65d74f68c8ee3cbd4a068fc415580c (diff)
r8169: offical fix for CVE-2009-4537 (overlength frame DMAs)
[ Upstream commit c0cd884af045338476b8e69a61fceb3f34ff22f1 ] Official patch to fix the r8169 frame length check error. Based on this initial thread: http://marc.info/?l=linux-netdev&m=126202972828626&w=1 This is the official patch to fix the frame length problems in the r8169 driver. As noted in the previous thread, while this patch incurs a performance hit on the driver, its possible to improve performance dynamically by updating the mtu and rx_copybreak values at runtime to return performance to what it was for those NICS which are unaffected by the ideosyncracy (if there are any). Summary: A while back Eric submitted a patch for r8169 in which the proper allocated frame size was written to RXMaxSize to prevent the NIC from dmaing too much data. This was done in commit fdd7b4c3302c93f6833e338903ea77245eb510b4. A long time prior to that however, Francois posted 126fa4b9ca5d9d7cb7d46f779ad3bd3631ca387c, which expiclitly disabled the MaxSize setting due to the fact that the hardware behaved in odd ways when overlong frames were received on NIC's supported by this driver. This was mentioned in a security conference recently: http://events.ccc.de/congress/2009/Fahrplan//events/3596.en.html It seems that if we can't enable frame size filtering, then, as Eric correctly noticed, we can find ourselves DMA-ing too much data to a buffer, causing corruption. As a result is seems that we are forced to allocate a frame which is ready to handle a maximally sized receive. This obviously has performance issues with it, so to mitigate that issue, this patch does two things: 1) Raises the copybreak value to the frame allocation size, which should force appropriately sized packets to get allocated on rx, rather than a full new 16k buffer. 2) This patch only disables frame filtering initially (i.e., during the NIC open), changing the MTU results in ring buffer allocation of a size in relation to the new mtu (along with a warning indicating that this is dangerous). Because of item (2), individuals who can't cope with the performance hit (or can otherwise filter frames to prevent the bug), or who have hardware they are sure is unaffected by this issue, can manually lower the copybreak and reset the mtu such that performance is restored easily. Signed-off-by: Neil Horman <nhorman@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/net/r8169.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 60f96c468a24..67d414b061d7 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -186,7 +186,12 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
186 186
187MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); 187MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
188 188
189static int rx_copybreak = 200; 189/*
190 * we set our copybreak very high so that we don't have
191 * to allocate 16k frames all the time (see note in
192 * rtl8169_open()
193 */
194static int rx_copybreak = 16383;
190static int use_dac; 195static int use_dac;
191static struct { 196static struct {
192 u32 msg_enable; 197 u32 msg_enable;
@@ -3245,9 +3250,13 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
3245} 3250}
3246 3251
3247static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, 3252static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
3248 struct net_device *dev) 3253 unsigned int mtu)
3249{ 3254{
3250 unsigned int max_frame = dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; 3255 unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
3256
3257 if (max_frame != 16383)
3258 printk(KERN_WARNING "WARNING! Changing of MTU on this NIC"
3259 "May lead to frame reception errors!\n");
3251 3260
3252 tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; 3261 tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE;
3253} 3262}
@@ -3259,7 +3268,17 @@ static int rtl8169_open(struct net_device *dev)
3259 int retval = -ENOMEM; 3268 int retval = -ENOMEM;
3260 3269
3261 3270
3262 rtl8169_set_rxbufsize(tp, dev); 3271 /*
3272 * Note that we use a magic value here, its wierd I know
3273 * its done because, some subset of rtl8169 hardware suffers from
3274 * a problem in which frames received that are longer than
3275 * the size set in RxMaxSize register return garbage sizes
3276 * when received. To avoid this we need to turn off filtering,
3277 * which is done by setting a value of 16383 in the RxMaxSize register
3278 * and allocating 16k frames to handle the largest possible rx value
3279 * thats what the magic math below does.
3280 */
3281 rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN);
3263 3282
3264 /* 3283 /*
3265 * Rx and Tx desscriptors needs 256 bytes alignment. 3284 * Rx and Tx desscriptors needs 256 bytes alignment.
@@ -3912,7 +3931,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
3912 3931
3913 rtl8169_down(dev); 3932 rtl8169_down(dev);
3914 3933
3915 rtl8169_set_rxbufsize(tp, dev); 3934 rtl8169_set_rxbufsize(tp, dev->mtu);
3916 3935
3917 ret = rtl8169_init_ring(dev); 3936 ret = rtl8169_init_ring(dev);
3918 if (ret < 0) 3937 if (ret < 0)