]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.drivers/fcoe-fix-frame-length-validati.diff
Disable build of xen kernel.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / fcoe-fix-frame-length-validati.diff
1 From: Chris Leech <christopher.leech@intel.com>
2 Subject: [FcOE] fix frame length validation in the early receive path
3 References: bnc #459142
4
5 Validation of the frame length was missing before accessing the FC and FCoE
6 headers. Some of the later checks were bogus, because of the way the fr_len
7 variable and skb->len were being manipulated they could never fail.
8
9 Signed-off-by: Chris Leech <christopher.leech@intel.com>
10 Acked-by: Bernhard Walle <bwalle@suse.de>
11 ---
12
13 drivers/scsi/fcoe/libfcoe.c | 48 +++++++++++++++++++++-----------------------
14 include/scsi/fc/fc_fcoe.h | 12 +++++++++++
15 include/scsi/fc_frame.h | 2 -
16 3 files changed, 36 insertions(+), 26 deletions(-)
17
18
19 --- a/drivers/scsi/fcoe/libfcoe.c
20 +++ b/drivers/scsi/fcoe/libfcoe.c
21 @@ -184,7 +184,6 @@ int fcoe_rcv(struct sk_buff *skb, struct
22 struct fcoe_rcv_info *fr;
23 struct fcoe_softc *fc;
24 struct fcoe_dev_stats *stats;
25 - u8 *data;
26 struct fc_frame_header *fh;
27 unsigned short oxid;
28 int cpu_idx;
29 @@ -211,9 +210,18 @@ int fcoe_rcv(struct sk_buff *skb, struct
30 FC_DBG("wrong FC type frame");
31 goto err;
32 }
33 - data = skb->data;
34 - data += sizeof(struct fcoe_hdr);
35 - fh = (struct fc_frame_header *)data;
36 +
37 + /*
38 + * Check for minimum frame length, and make sure required FCoE
39 + * and FC headers are pulled into the linear data area.
40 + */
41 + if (unlikely((skb->len < FCOE_MIN_FRAME) ||
42 + !pskb_may_pull(skb, FCOE_HEADER_LEN)))
43 + goto err;
44 +
45 + skb_set_transport_header(skb, sizeof(struct fcoe_hdr));
46 + fh = (struct fc_frame_header *) skb_transport_header(skb);
47 +
48 oxid = ntohs(fh->fh_ox_id);
49
50 fr = fcoe_dev_from_skb(skb);
51 @@ -514,8 +522,6 @@ int fcoe_percpu_receive_thread(void *arg
52 {
53 struct fcoe_percpu_s *p = arg;
54 u32 fr_len;
55 - unsigned int hlen;
56 - unsigned int tlen;
57 struct fc_lport *lp;
58 struct fcoe_rcv_info *fr;
59 struct fcoe_dev_stats *stats;
60 @@ -572,10 +578,12 @@ int fcoe_percpu_receive_thread(void *arg
61 skb_linearize(skb); /* not ideal */
62
63 /*
64 - * Check the header and pull it off.
65 + * Frame length checks and setting up the header pointers
66 + * was done in fcoe_rcv already.
67 */
68 - hlen = sizeof(struct fcoe_hdr);
69 - hp = (struct fcoe_hdr *)skb->data;
70 + hp = (struct fcoe_hdr *) skb_network_header(skb);
71 + fh = (struct fc_frame_header *) skb_transport_header(skb);
72 +
73 if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
74 if (stats) {
75 if (stats->ErrorFrames < 5)
76 @@ -586,22 +594,10 @@ int fcoe_percpu_receive_thread(void *arg
77 kfree_skb(skb);
78 continue;
79 }
80 +
81 skb_pull(skb, sizeof(struct fcoe_hdr));
82 - tlen = sizeof(struct fcoe_crc_eof);
83 - fr_len = skb->len - tlen;
84 - skb_trim(skb, fr_len);
85 + fr_len = skb->len - sizeof(struct fcoe_crc_eof);
86
87 - if (unlikely(fr_len > skb->len)) {
88 - if (stats) {
89 - if (stats->ErrorFrames < 5)
90 - FC_DBG("length error fr_len 0x%x "
91 - "skb->len 0x%x", fr_len,
92 - skb->len);
93 - stats->ErrorFrames++;
94 - }
95 - kfree_skb(skb);
96 - continue;
97 - }
98 if (stats) {
99 stats->RxFrames++;
100 stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
101 @@ -610,9 +606,11 @@ int fcoe_percpu_receive_thread(void *arg
102 fp = (struct fc_frame *)skb;
103 cp = (struct fcoe_crc_eof *)(skb->data + fr_len);
104 fc_frame_init(fp);
105 - fr_eof(fp) = cp->fcoe_eof;
106 - fr_sof(fp) = hp->fcoe_sof;
107 fr_dev(fp) = lp;
108 + fr_sof(fp) = hp->fcoe_sof;
109 + fr_eof(fp) = cp->fcoe_eof;
110 + /* trim off the CRC and EOF trailer*/
111 + skb_trim(skb, fr_len);
112
113 /*
114 * We only check CRC if no offload is available and if it is
115 --- a/include/scsi/fc/fc_fcoe.h
116 +++ b/include/scsi/fc/fc_fcoe.h
117 @@ -85,6 +85,18 @@ struct fcoe_crc_eof {
118 } __attribute__((packed));
119
120 /*
121 + * Minimum FCoE + FC header length
122 + * 14 bytes FCoE header + 24 byte FC header = 38 bytes
123 + */
124 +#define FCOE_HEADER_LEN 38
125 +
126 +/*
127 + * Minimum FCoE frame size
128 + * 14 bytes FCoE header + 24 byte FC header + 8 byte FCoE trailer = 46 bytes
129 + */
130 +#define FCOE_MIN_FRAME 46
131 +
132 +/*
133 * fc_fcoe_set_mac - Store OUI + DID into MAC address field.
134 * @mac: mac address to be set
135 * @did: fc dest id to use
136 --- a/include/scsi/fc_frame.h
137 +++ b/include/scsi/fc_frame.h
138 @@ -66,10 +66,10 @@ struct fcoe_rcv_info {
139 struct fc_lport *fr_dev; /* transport layer private pointer */
140 struct fc_seq *fr_seq; /* for use with exchange manager */
141 struct scsi_cmnd *fr_cmd; /* for use of scsi command */
142 + u16 fr_max_payload; /* max FC payload */
143 enum fc_sof fr_sof; /* start of frame delimiter */
144 enum fc_eof fr_eof; /* end of frame delimiter */
145 u8 fr_flags; /* flags - see below */
146 - u16 fr_max_payload; /* max FC payload */
147 };
148
149 /*