aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_statefuns.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2009-09-04 18:21:03 -0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2009-09-04 18:21:03 -0400
commitf1751c57f7bb816c9b6b4cb5d79c703aaa7199da (patch)
tree68e75889f4fd4b576f50bd52088c79f7c837323d /net/sctp/sm_statefuns.c
parentbe2971438dec2e2d041af4701472a93a7dd03642 (diff)
sctp: Catch bogus stream sequence numbers
Since our TSN map is capable of holding at most a 4K chunk gap, there is no way that during this gap, a stream sequence number (unsigned short) can wrap such that the new number is smaller then the next expected one. If such a case is encountered, this is a protocol violation. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Diffstat (limited to 'net/sctp/sm_statefuns.c')
-rw-r--r--net/sctp/sm_statefuns.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index a7f18a352364..c8fae1983dd1 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -2891,6 +2891,9 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
2891 goto discard_force; 2891 goto discard_force;
2892 case SCTP_IERROR_NO_DATA: 2892 case SCTP_IERROR_NO_DATA:
2893 goto consume; 2893 goto consume;
2894 case SCTP_IERROR_PROTO_VIOLATION:
2895 return sctp_sf_abort_violation(ep, asoc, chunk, commands,
2896 (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t));
2894 default: 2897 default:
2895 BUG(); 2898 BUG();
2896 } 2899 }
@@ -3001,6 +3004,9 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
3001 break; 3004 break;
3002 case SCTP_IERROR_NO_DATA: 3005 case SCTP_IERROR_NO_DATA:
3003 goto consume; 3006 goto consume;
3007 case SCTP_IERROR_PROTO_VIOLATION:
3008 return sctp_sf_abort_violation(ep, asoc, chunk, commands,
3009 (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t));
3004 default: 3010 default:
3005 BUG(); 3011 BUG();
3006 } 3012 }
@@ -5877,6 +5883,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
5877 __u32 tsn; 5883 __u32 tsn;
5878 struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; 5884 struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
5879 struct sock *sk = asoc->base.sk; 5885 struct sock *sk = asoc->base.sk;
5886 u16 ssn;
5887 u16 sid;
5888 u8 ordered = 0;
5880 5889
5881 data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data; 5890 data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
5882 skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); 5891 skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
@@ -6016,8 +6025,10 @@ static int sctp_eat_data(const struct sctp_association *asoc,
6016 */ 6025 */
6017 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) 6026 if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
6018 SCTP_INC_STATS(SCTP_MIB_INUNORDERCHUNKS); 6027 SCTP_INC_STATS(SCTP_MIB_INUNORDERCHUNKS);
6019 else 6028 else {
6020 SCTP_INC_STATS(SCTP_MIB_INORDERCHUNKS); 6029 SCTP_INC_STATS(SCTP_MIB_INORDERCHUNKS);
6030 ordered = 1;
6031 }
6021 6032
6022 /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number 6033 /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
6023 * 6034 *
@@ -6027,7 +6038,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
6027 * with cause set to "Invalid Stream Identifier" (See Section 3.3.10) 6038 * with cause set to "Invalid Stream Identifier" (See Section 3.3.10)
6028 * and discard the DATA chunk. 6039 * and discard the DATA chunk.
6029 */ 6040 */
6030 if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) { 6041 sid = ntohs(data_hdr->stream);
6042 if (sid >= asoc->c.sinit_max_instreams) {
6031 /* Mark tsn as received even though we drop it */ 6043 /* Mark tsn as received even though we drop it */
6032 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); 6044 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
6033 6045
@@ -6040,6 +6052,18 @@ static int sctp_eat_data(const struct sctp_association *asoc,
6040 return SCTP_IERROR_BAD_STREAM; 6052 return SCTP_IERROR_BAD_STREAM;
6041 } 6053 }
6042 6054
6055 /* Check to see if the SSN is possible for this TSN.
6056 * The biggest gap we can record is 4K wide. Since SSNs wrap
6057 * at an unsigned short, there is no way that an SSN can
6058 * wrap and for a valid TSN. We can simply check if the current
6059 * SSN is smaller then the next expected one. If it is, it wrapped
6060 * and is invalid.
6061 */
6062 ssn = ntohs(data_hdr->ssn);
6063 if (ordered && SSN_lt(ssn, sctp_ssn_peek(&asoc->ssnmap->in, sid))) {
6064 return SCTP_IERROR_PROTO_VIOLATION;
6065 }
6066
6043 /* Send the data up to the user. Note: Schedule the 6067 /* Send the data up to the user. Note: Schedule the
6044 * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK 6068 * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK
6045 * chunk needs the updated rwnd. 6069 * chunk needs the updated rwnd.