r8169: offical fix for CVE-2009-4537 (overlength frame DMAs)

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>

authored by Neil Horman and committed by David S. Miller c0cd884a 54c1a859

+24 -5
+24 -5
drivers/net/r8169.c
··· 186 186 187 187 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); 188 188 189 - static 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 + */ 194 + static int rx_copybreak = 16383; 190 195 static int use_dac; 191 196 static struct { 192 197 u32 msg_enable; ··· 3222 3217 } 3223 3218 3224 3219 static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, 3225 - struct net_device *dev) 3220 + unsigned int mtu) 3226 3221 { 3227 - unsigned int max_frame = dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; 3222 + unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; 3223 + 3224 + if (max_frame != 16383) 3225 + printk(KERN_WARNING "WARNING! Changing of MTU on this NIC" 3226 + "May lead to frame reception errors!\n"); 3228 3227 3229 3228 tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; 3230 3229 } ··· 3240 3231 int retval = -ENOMEM; 3241 3232 3242 3233 3243 - rtl8169_set_rxbufsize(tp, dev); 3234 + /* 3235 + * Note that we use a magic value here, its wierd I know 3236 + * its done because, some subset of rtl8169 hardware suffers from 3237 + * a problem in which frames received that are longer than 3238 + * the size set in RxMaxSize register return garbage sizes 3239 + * when received. To avoid this we need to turn off filtering, 3240 + * which is done by setting a value of 16383 in the RxMaxSize register 3241 + * and allocating 16k frames to handle the largest possible rx value 3242 + * thats what the magic math below does. 3243 + */ 3244 + rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN); 3244 3245 3245 3246 /* 3246 3247 * Rx and Tx desscriptors needs 256 bytes alignment. ··· 3903 3884 3904 3885 rtl8169_down(dev); 3905 3886 3906 - rtl8169_set_rxbufsize(tp, dev); 3887 + rtl8169_set_rxbufsize(tp, dev->mtu); 3907 3888 3908 3889 ret = rtl8169_init_ring(dev); 3909 3890 if (ret < 0)