]>
Commit | Line | Data |
---|---|---|
1c771352 WB |
1 | From a7278b36fcab9af469563bd7b9dadebe2ae25e48 Mon Sep 17 00:00:00 2001 |
2 | From: Dana Rubin <dana.rubin@ravellosystems.com> | |
3 | Date: Tue, 18 Aug 2015 12:45:55 +0300 | |
4 | Subject: [PATCH] net/vmxnet3: Refine l2 header validation | |
5 | ||
6 | Validation of l2 header length assumed minimal packet size as | |
7 | eth_header + 2 * vlan_header regardless of the actual protocol. | |
8 | ||
9 | This caused crash for valid non-IP packets shorter than 22 bytes, as | |
10 | 'tx_pkt->packet_type' hasn't been assigned for such packets, and | |
11 | 'vmxnet3_on_tx_done_update_stats()' expects it to be properly set. | |
12 | ||
13 | Refine header length validation in 'vmxnet_tx_pkt_parse_headers'. | |
14 | Check its return value during packet processing flow. | |
15 | ||
16 | As a side effect, in case IPv4 and IPv6 header validation failure, | |
17 | corrupt packets will be dropped. | |
18 | ||
19 | Signed-off-by: Dana Rubin <dana.rubin@ravellosystems.com> | |
20 | Signed-off-by: Shmulik Ladkani <shmulik.ladkani@ravellosystems.com> | |
21 | Signed-off-by: Jason Wang <jasowang@redhat.com> | |
22 | --- | |
23 | hw/net/vmxnet3.c | 4 +--- | |
24 | hw/net/vmxnet_tx_pkt.c | 19 ++++++++++++++++--- | |
25 | 2 files changed, 17 insertions(+), 6 deletions(-) | |
26 | ||
27 | diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c | |
28 | index 04159c8..48ced71 100644 | |
29 | --- a/hw/net/vmxnet3.c | |
30 | +++ b/hw/net/vmxnet3.c | |
31 | @@ -729,9 +729,7 @@ static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx) | |
32 | } | |
33 | ||
34 | if (txd.eop) { | |
35 | - if (!s->skip_current_tx_pkt) { | |
36 | - vmxnet_tx_pkt_parse(s->tx_pkt); | |
37 | - | |
38 | + if (!s->skip_current_tx_pkt && vmxnet_tx_pkt_parse(s->tx_pkt)) { | |
39 | if (s->needs_vlan) { | |
40 | vmxnet_tx_pkt_setup_vlan_header(s->tx_pkt, s->tci); | |
41 | } | |
42 | diff --git a/hw/net/vmxnet_tx_pkt.c b/hw/net/vmxnet_tx_pkt.c | |
43 | index f7344c4..eb88ddf 100644 | |
44 | --- a/hw/net/vmxnet_tx_pkt.c | |
45 | +++ b/hw/net/vmxnet_tx_pkt.c | |
46 | @@ -142,11 +142,24 @@ static bool vmxnet_tx_pkt_parse_headers(struct VmxnetTxPkt *pkt) | |
47 | ||
48 | bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags, 0, l2_hdr->iov_base, | |
49 | ETH_MAX_L2_HDR_LEN); | |
50 | - if (bytes_read < ETH_MAX_L2_HDR_LEN) { | |
51 | + if (bytes_read < sizeof(struct eth_header)) { | |
52 | + l2_hdr->iov_len = 0; | |
53 | + return false; | |
54 | + } | |
55 | + | |
56 | + l2_hdr->iov_len = sizeof(struct eth_header); | |
57 | + switch (be16_to_cpu(PKT_GET_ETH_HDR(l2_hdr->iov_base)->h_proto)) { | |
58 | + case ETH_P_VLAN: | |
59 | + l2_hdr->iov_len += sizeof(struct vlan_header); | |
60 | + break; | |
61 | + case ETH_P_DVLAN: | |
62 | + l2_hdr->iov_len += 2 * sizeof(struct vlan_header); | |
63 | + break; | |
64 | + } | |
65 | + | |
66 | + if (bytes_read < l2_hdr->iov_len) { | |
67 | l2_hdr->iov_len = 0; | |
68 | return false; | |
69 | - } else { | |
70 | - l2_hdr->iov_len = eth_get_l2_hdr_length(l2_hdr->iov_base); | |
71 | } | |
72 | ||
73 | l3_proto = eth_get_l3_proto(l2_hdr->iov_base, l2_hdr->iov_len); | |
74 | -- | |
75 | 2.1.4 | |
76 |