diff options
| author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2009-11-23 15:53:56 -0500 |
|---|---|---|
| committer | Vlad Yasevich <vladislav.yasevich@hp.com> | 2009-11-23 15:53:56 -0500 |
| commit | 6383cfb3ed3c5c0bea06da0099c219ef4237ecf5 (patch) | |
| tree | e3bfb43500b664c5a572d0a9456d7e7ec4f7aeab | |
| parent | b93d6471748de2ce02cc24774b774deb306a57a8 (diff) | |
sctp: Fix malformed "Invalid Stream Identifier" error
The "Invalid Stream Identifier" error has a 16 bit reserved
field at the end, thus making the parameter length be 8 bytes.
We've never supplied that reserved field making wireshark
tag the packet as malformed.
Reported-by: Chris Dischino <cdischino@sonusnet.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
| -rw-r--r-- | include/net/sctp/sm.h | 3 | ||||
| -rw-r--r-- | net/sctp/sm_make_chunk.c | 13 | ||||
| -rw-r--r-- | net/sctp/sm_statefuns.c | 13 |
3 files changed, 19 insertions, 10 deletions
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index c1dd89365833..851c813adb3a 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h | |||
| @@ -243,7 +243,8 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *, | |||
| 243 | const struct sctp_chunk *chunk, | 243 | const struct sctp_chunk *chunk, |
| 244 | __be16 cause_code, | 244 | __be16 cause_code, |
| 245 | const void *payload, | 245 | const void *payload, |
| 246 | size_t paylen); | 246 | size_t paylen, |
| 247 | size_t reserve_tail); | ||
| 247 | 248 | ||
| 248 | struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *, | 249 | struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *, |
| 249 | union sctp_addr *, | 250 | union sctp_addr *, |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9d881a61ac02..9e732916b671 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -987,7 +987,10 @@ static void *sctp_addto_param(struct sctp_chunk *chunk, int len, | |||
| 987 | 987 | ||
| 988 | target = skb_put(chunk->skb, len); | 988 | target = skb_put(chunk->skb, len); |
| 989 | 989 | ||
| 990 | memcpy(target, data, len); | 990 | if (data) |
| 991 | memcpy(target, data, len); | ||
| 992 | else | ||
| 993 | memset(target, 0, len); | ||
| 991 | 994 | ||
| 992 | /* Adjust the chunk length field. */ | 995 | /* Adjust the chunk length field. */ |
| 993 | chunk->chunk_hdr->length = htons(chunklen + len); | 996 | chunk->chunk_hdr->length = htons(chunklen + len); |
| @@ -1129,16 +1132,18 @@ nodata: | |||
| 1129 | struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, | 1132 | struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, |
| 1130 | const struct sctp_chunk *chunk, | 1133 | const struct sctp_chunk *chunk, |
| 1131 | __be16 cause_code, const void *payload, | 1134 | __be16 cause_code, const void *payload, |
| 1132 | size_t paylen) | 1135 | size_t paylen, size_t reserve_tail) |
| 1133 | { | 1136 | { |
| 1134 | struct sctp_chunk *retval; | 1137 | struct sctp_chunk *retval; |
| 1135 | 1138 | ||
| 1136 | retval = sctp_make_op_error_space(asoc, chunk, paylen); | 1139 | retval = sctp_make_op_error_space(asoc, chunk, paylen + reserve_tail); |
| 1137 | if (!retval) | 1140 | if (!retval) |
| 1138 | goto nodata; | 1141 | goto nodata; |
| 1139 | 1142 | ||
| 1140 | sctp_init_cause(retval, cause_code, paylen); | 1143 | sctp_init_cause(retval, cause_code, paylen + reserve_tail); |
| 1141 | sctp_addto_chunk(retval, paylen, payload); | 1144 | sctp_addto_chunk(retval, paylen, payload); |
| 1145 | if (reserve_tail) | ||
| 1146 | sctp_addto_param(retval, reserve_tail, NULL); | ||
| 1142 | 1147 | ||
| 1143 | nodata: | 1148 | nodata: |
| 1144 | return retval; | 1149 | return retval; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8ee24c9dc7e9..16a603527df2 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -1720,7 +1720,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
| 1720 | 1720 | ||
| 1721 | err = sctp_make_op_error(asoc, chunk, | 1721 | err = sctp_make_op_error(asoc, chunk, |
| 1722 | SCTP_ERROR_COOKIE_IN_SHUTDOWN, | 1722 | SCTP_ERROR_COOKIE_IN_SHUTDOWN, |
| 1723 | NULL, 0); | 1723 | NULL, 0, 0); |
| 1724 | if (err) | 1724 | if (err) |
| 1725 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 1725 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
| 1726 | SCTP_CHUNK(err)); | 1726 | SCTP_CHUNK(err)); |
| @@ -3977,7 +3977,7 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep, | |||
| 3977 | err_chunk = sctp_make_op_error(asoc, chunk, | 3977 | err_chunk = sctp_make_op_error(asoc, chunk, |
| 3978 | SCTP_ERROR_UNSUP_HMAC, | 3978 | SCTP_ERROR_UNSUP_HMAC, |
| 3979 | &auth_hdr->hmac_id, | 3979 | &auth_hdr->hmac_id, |
| 3980 | sizeof(__u16)); | 3980 | sizeof(__u16), 0); |
| 3981 | if (err_chunk) { | 3981 | if (err_chunk) { |
| 3982 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 3982 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
| 3983 | SCTP_CHUNK(err_chunk)); | 3983 | SCTP_CHUNK(err_chunk)); |
| @@ -4069,7 +4069,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | |||
| 4069 | hdr = unk_chunk->chunk_hdr; | 4069 | hdr = unk_chunk->chunk_hdr; |
| 4070 | err_chunk = sctp_make_op_error(asoc, unk_chunk, | 4070 | err_chunk = sctp_make_op_error(asoc, unk_chunk, |
| 4071 | SCTP_ERROR_UNKNOWN_CHUNK, hdr, | 4071 | SCTP_ERROR_UNKNOWN_CHUNK, hdr, |
| 4072 | WORD_ROUND(ntohs(hdr->length))); | 4072 | WORD_ROUND(ntohs(hdr->length)), |
| 4073 | 0); | ||
| 4073 | if (err_chunk) { | 4074 | if (err_chunk) { |
| 4074 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 4075 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
| 4075 | SCTP_CHUNK(err_chunk)); | 4076 | SCTP_CHUNK(err_chunk)); |
| @@ -4088,7 +4089,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | |||
| 4088 | hdr = unk_chunk->chunk_hdr; | 4089 | hdr = unk_chunk->chunk_hdr; |
| 4089 | err_chunk = sctp_make_op_error(asoc, unk_chunk, | 4090 | err_chunk = sctp_make_op_error(asoc, unk_chunk, |
| 4090 | SCTP_ERROR_UNKNOWN_CHUNK, hdr, | 4091 | SCTP_ERROR_UNKNOWN_CHUNK, hdr, |
| 4091 | WORD_ROUND(ntohs(hdr->length))); | 4092 | WORD_ROUND(ntohs(hdr->length)), |
| 4093 | 0); | ||
| 4092 | if (err_chunk) { | 4094 | if (err_chunk) { |
| 4093 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 4095 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
| 4094 | SCTP_CHUNK(err_chunk)); | 4096 | SCTP_CHUNK(err_chunk)); |
| @@ -6052,7 +6054,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
| 6052 | 6054 | ||
| 6053 | err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, | 6055 | err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, |
| 6054 | &data_hdr->stream, | 6056 | &data_hdr->stream, |
| 6055 | sizeof(data_hdr->stream)); | 6057 | sizeof(data_hdr->stream), |
| 6058 | sizeof(u16)); | ||
| 6056 | if (err) | 6059 | if (err) |
| 6057 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 6060 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
| 6058 | SCTP_CHUNK(err)); | 6061 | SCTP_CHUNK(err)); |
