]>
Commit | Line | Data |
---|---|---|
4d1e5b62 AF |
1 | From: Chris Leech <christopher.leech@intel.com> |
2 | Subject: [FcOE] make RSCN parsing more robust | |
3 | References: bnc #459142 | |
4 | ||
5 | RSCN parsing needs to verify that the payload length specified in the RSCN ELS | |
6 | message does not exceed the size of the actual frame received. | |
7 | ||
8 | Signed-off-by: Chris Leech <christopher.leech@intel.com> | |
9 | Acked-by: Bernhard Walle <bwalle@suse.de> | |
10 | --- | |
11 | ||
12 | drivers/scsi/libfc/fc_disc.c | 19 +++++++++++++++---- | |
13 | 1 files changed, 15 insertions(+), 4 deletions(-) | |
14 | ||
15 | ||
16 | diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c | |
17 | index 0416041..8b609e4 100644 | |
18 | --- a/drivers/scsi/libfc/fc_disc.c | |
19 | +++ b/drivers/scsi/libfc/fc_disc.c | |
20 | @@ -173,17 +173,27 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, | |
21 | FC_DEBUG_DISC("Received an RSCN event on port (%6x)\n", | |
22 | fc_host_port_id(lport->host)); | |
23 | ||
24 | + /* make sure the frame contains an RSCN message */ | |
25 | rp = fc_frame_payload_get(fp, sizeof(*rp)); | |
26 | - | |
27 | - if (!rp || rp->rscn_page_len != sizeof(*pp)) | |
28 | + if (!rp) | |
29 | goto reject; | |
30 | - | |
31 | + /* make sure the page length is as expected (4 bytes) */ | |
32 | + if (rp->rscn_page_len != sizeof(*pp)) | |
33 | + goto reject; | |
34 | + /* get the RSCN payload length */ | |
35 | len = ntohs(rp->rscn_plen); | |
36 | if (len < sizeof(*rp)) | |
37 | goto reject; | |
38 | + /* make sure the frame contains the expected payload */ | |
39 | + rp = fc_frame_payload_get(fp, len); | |
40 | + if (!rp) | |
41 | + goto reject; | |
42 | + /* payload must be a multiple of the RSCN page size */ | |
43 | len -= sizeof(*rp); | |
44 | + if (len % sizeof(*pp)) | |
45 | + goto reject; | |
46 | ||
47 | - for (pp = (void *)(rp + 1); len; len -= sizeof(*pp), pp++) { | |
48 | + for (pp = (void *)(rp + 1); len > 0; len -= sizeof(*pp), pp++) { | |
49 | ev_qual = pp->rscn_page_flags >> ELS_RSCN_EV_QUAL_BIT; | |
50 | ev_qual &= ELS_RSCN_EV_QUAL_MASK; | |
51 | fmt = pp->rscn_page_flags >> ELS_RSCN_ADDR_FMT_BIT; | |
52 | @@ -239,6 +249,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, | |
53 | fc_frame_free(fp); | |
54 | return; | |
55 | reject: | |
56 | + FC_DEBUG_DISC("Received a bad RSCN frame\n"); | |
57 | rjt_data.fp = NULL; | |
58 | rjt_data.reason = ELS_RJT_LOGIC; | |
59 | rjt_data.explan = ELS_EXPL_NONE; |