| From 3d41c2bd66b1618aa1062c3d98450a9a5f0d119e Mon Sep 17 00:00:00 2001 |
| From: Wei Yongjun <yjwei@cn.fujitsu.com> |
| Date: Tue, 20 Jan 2009 14:08:01 -0800 |
| Subject: sctp: Avoid memory overflow while FWD-TSN chunk is received with bad stream ID |
| |
| From: Wei Yongjun <yjwei@cn.fujitsu.com> |
| |
| [ Upstream commit: 9fcb95a105758b81ef0131cd18e2db5149f13e95 ] |
| |
| If FWD-TSN chunk is received with bad stream ID, the sctp will not do the |
| validity check, this may cause memory overflow when overwrite the TSN of |
| the stream ID. |
| |
| The FORWARD-TSN chunk is like this: |
| |
| FORWARD-TSN chunk |
| Type = 192 |
| Flags = 0 |
| Length = 172 |
| NewTSN = 99 |
| Stream = 10000 |
| StreamSequence = 0xFFFF |
| |
| This patch fix this problem by discard the chunk if stream ID is not |
| less than MIS. |
| |
| Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> |
| Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| net/sctp/sm_statefuns.c | 14 ++++++++++++++ |
| 1 file changed, 14 insertions(+) |
| |
| --- a/net/sctp/sm_statefuns.c |
| +++ b/net/sctp/sm_statefuns.c |
| @@ -3691,6 +3691,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(c |
| { |
| struct sctp_chunk *chunk = arg; |
| struct sctp_fwdtsn_hdr *fwdtsn_hdr; |
| + struct sctp_fwdtsn_skip *skip; |
| __u16 len; |
| __u32 tsn; |
| |
| @@ -3720,6 +3721,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(c |
| if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) |
| goto discard_noforce; |
| |
| + /* Silently discard the chunk if stream-id is not valid */ |
| + sctp_walk_fwdtsn(skip, chunk) { |
| + if (ntohs(skip->stream) >= asoc->c.sinit_max_instreams) |
| + goto discard_noforce; |
| + } |
| + |
| sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); |
| if (len > sizeof(struct sctp_fwdtsn_hdr)) |
| sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, |
| @@ -3751,6 +3758,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_f |
| { |
| struct sctp_chunk *chunk = arg; |
| struct sctp_fwdtsn_hdr *fwdtsn_hdr; |
| + struct sctp_fwdtsn_skip *skip; |
| __u16 len; |
| __u32 tsn; |
| |
| @@ -3780,6 +3788,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_f |
| if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) |
| goto gen_shutdown; |
| |
| + /* Silently discard the chunk if stream-id is not valid */ |
| + sctp_walk_fwdtsn(skip, chunk) { |
| + if (ntohs(skip->stream) >= asoc->c.sinit_max_instreams) |
| + goto gen_shutdown; |
| + } |
| + |
| sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); |
| if (len > sizeof(struct sctp_fwdtsn_hdr)) |
| sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, |