aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2015-11-16 07:36:32 -0500
committerDavid S. Miller <davem@davemloft.net>2015-11-17 14:37:16 -0500
commit6c606fa32c4272894248c1abbc15257fc04250be (patch)
treed9e2e25169454d4c8c64b5ce9eae52f3407b099f
parentf1a454a37618b819f2528ccd234f77a02b3a6016 (diff)
via-velocity: unconditionally drop frames with bad l2 length
By default the driver allowed incorrect frames to be received. What is worse the code does not handle very short frames correctly. The FCS length is unconditionally subtracted, and the underflow can cause skb_put to be called with large number after implicit cast to unsigned. And indeed, an skb_over_panic() was observed with via-velocity. This removes the module parameter as it does not work in it's current state, and should be implemented via NETIF_F_RXALL if needed. Suggested-by: Francois Romieu <romieu@fr.zoreil.com> Signed-off-by: Timo Teräs <timo.teras@iki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/via/via-velocity.c24
1 files changed, 3 insertions, 21 deletions
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index ae68afd50a15..f38696ceee74 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -345,13 +345,6 @@ VELOCITY_PARAM(flow_control, "Enable flow control ability");
345*/ 345*/
346VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode"); 346VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode");
347 347
348#define VAL_PKT_LEN_DEF 0
349/* ValPktLen[] is used for setting the checksum offload ability of NIC.
350 0: Receive frame with invalid layer 2 length (Default)
351 1: Drop frame with invalid layer 2 length
352*/
353VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame");
354
355#define WOL_OPT_DEF 0 348#define WOL_OPT_DEF 0
356#define WOL_OPT_MIN 0 349#define WOL_OPT_MIN 0
357#define WOL_OPT_MAX 7 350#define WOL_OPT_MAX 7
@@ -494,7 +487,6 @@ static void velocity_get_options(struct velocity_opt *opts, int index,
494 487
495 velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname); 488 velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname);
496 velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname); 489 velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname);
497 velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname);
498 velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname); 490 velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname);
499 velocity_set_int_opt(&opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname); 491 velocity_set_int_opt(&opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);
500 opts->numrx = (opts->numrx & ~3); 492 opts->numrx = (opts->numrx & ~3);
@@ -2055,8 +2047,9 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
2055 int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff; 2047 int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff;
2056 struct sk_buff *skb; 2048 struct sk_buff *skb;
2057 2049
2058 if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) { 2050 if (unlikely(rd->rdesc0.RSR & (RSR_STP | RSR_EDP | RSR_RL))) {
2059 VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame spans multiple RDs.\n", vptr->netdev->name); 2051 if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP))
2052 VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame spans multiple RDs.\n", vptr->netdev->name);
2060 stats->rx_length_errors++; 2053 stats->rx_length_errors++;
2061 return -EINVAL; 2054 return -EINVAL;
2062 } 2055 }
@@ -2069,17 +2062,6 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
2069 dma_sync_single_for_cpu(vptr->dev, rd_info->skb_dma, 2062 dma_sync_single_for_cpu(vptr->dev, rd_info->skb_dma,
2070 vptr->rx.buf_sz, DMA_FROM_DEVICE); 2063 vptr->rx.buf_sz, DMA_FROM_DEVICE);
2071 2064
2072 /*
2073 * Drop frame not meeting IEEE 802.3
2074 */
2075
2076 if (vptr->flags & VELOCITY_FLAGS_VAL_PKT_LEN) {
2077 if (rd->rdesc0.RSR & RSR_RL) {
2078 stats->rx_length_errors++;
2079 return -EINVAL;
2080 }
2081 }
2082
2083 velocity_rx_csum(rd, skb); 2065 velocity_rx_csum(rd, skb);
2084 2066
2085 if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) { 2067 if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) {