aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_statefuns.c
diff options
context:
space:
mode:
authorWei Yongjun <yjwei@cn.fujitsu.com>2007-09-19 05:19:52 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-09-26 01:55:49 -0400
commit6f4c618ddb0e6b7e6d49cfc8134e694be1c0bc9b (patch)
tree7ff3a0de1fc54e82bca9201d7f3d5df5c43c7cc7 /net/sctp/sm_statefuns.c
parent3c77f961b55b6060858c68a213d7f4470d7f3eb2 (diff)
SCTP : Add paramters validity check for ASCONF chunk
If ADDIP is enabled, when an ASCONF chunk is received with ASCONF paramter length set to zero, this will cause infinite loop. By the way, if an malformed ASCONF chunk is received, will cause processing to access memory without verifying. This is because of not check the validity of parameters in ASCONF chunk. This patch fixed this. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Diffstat (limited to 'net/sctp/sm_statefuns.c')
-rw-r--r--net/sctp/sm_statefuns.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index caed19d90d0..a583d67cab6 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -117,6 +117,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
117 void *arg, 117 void *arg,
118 sctp_cmd_seq_t *commands); 118 sctp_cmd_seq_t *commands);
119 119
120static sctp_disposition_t sctp_sf_violation_paramlen(
121 const struct sctp_endpoint *ep,
122 const struct sctp_association *asoc,
123 const sctp_subtype_t type,
124 void *arg,
125 sctp_cmd_seq_t *commands);
126
120static sctp_disposition_t sctp_sf_violation_ctsn( 127static sctp_disposition_t sctp_sf_violation_ctsn(
121 const struct sctp_endpoint *ep, 128 const struct sctp_endpoint *ep,
122 const struct sctp_association *asoc, 129 const struct sctp_association *asoc,
@@ -3296,8 +3303,11 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
3296{ 3303{
3297 struct sctp_chunk *chunk = arg; 3304 struct sctp_chunk *chunk = arg;
3298 struct sctp_chunk *asconf_ack = NULL; 3305 struct sctp_chunk *asconf_ack = NULL;
3306 struct sctp_paramhdr *err_param = NULL;
3299 sctp_addiphdr_t *hdr; 3307 sctp_addiphdr_t *hdr;
3308 union sctp_addr_param *addr_param;
3300 __u32 serial; 3309 __u32 serial;
3310 int length;
3301 3311
3302 if (!sctp_vtag_verify(chunk, asoc)) { 3312 if (!sctp_vtag_verify(chunk, asoc)) {
3303 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 3313 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
@@ -3313,6 +3323,20 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
3313 hdr = (sctp_addiphdr_t *)chunk->skb->data; 3323 hdr = (sctp_addiphdr_t *)chunk->skb->data;
3314 serial = ntohl(hdr->serial); 3324 serial = ntohl(hdr->serial);
3315 3325
3326 addr_param = (union sctp_addr_param *)hdr->params;
3327 length = ntohs(addr_param->p.length);
3328 if (length < sizeof(sctp_paramhdr_t))
3329 return sctp_sf_violation_paramlen(ep, asoc, type,
3330 (void *)addr_param, commands);
3331
3332 /* Verify the ASCONF chunk before processing it. */
3333 if (!sctp_verify_asconf(asoc,
3334 (sctp_paramhdr_t *)((void *)addr_param + length),
3335 (void *)chunk->chunk_end,
3336 &err_param))
3337 return sctp_sf_violation_paramlen(ep, asoc, type,
3338 (void *)&err_param, commands);
3339
3316 /* ADDIP 4.2 C1) Compare the value of the serial number to the value 3340 /* ADDIP 4.2 C1) Compare the value of the serial number to the value
3317 * the endpoint stored in a new association variable 3341 * the endpoint stored in a new association variable
3318 * 'Peer-Serial-Number'. 3342 * 'Peer-Serial-Number'.
@@ -3367,6 +3391,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
3367 struct sctp_chunk *asconf_ack = arg; 3391 struct sctp_chunk *asconf_ack = arg;
3368 struct sctp_chunk *last_asconf = asoc->addip_last_asconf; 3392 struct sctp_chunk *last_asconf = asoc->addip_last_asconf;
3369 struct sctp_chunk *abort; 3393 struct sctp_chunk *abort;
3394 struct sctp_paramhdr *err_param = NULL;
3370 sctp_addiphdr_t *addip_hdr; 3395 sctp_addiphdr_t *addip_hdr;
3371 __u32 sent_serial, rcvd_serial; 3396 __u32 sent_serial, rcvd_serial;
3372 3397
@@ -3384,6 +3409,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
3384 addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data; 3409 addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data;
3385 rcvd_serial = ntohl(addip_hdr->serial); 3410 rcvd_serial = ntohl(addip_hdr->serial);
3386 3411
3412 /* Verify the ASCONF-ACK chunk before processing it. */
3413 if (!sctp_verify_asconf(asoc,
3414 (sctp_paramhdr_t *)addip_hdr->params,
3415 (void *)asconf_ack->chunk_end,
3416 &err_param))
3417 return sctp_sf_violation_paramlen(ep, asoc, type,
3418 (void *)&err_param, commands);
3419
3387 if (last_asconf) { 3420 if (last_asconf) {
3388 addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; 3421 addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr;
3389 sent_serial = ntohl(addip_hdr->serial); 3422 sent_serial = ntohl(addip_hdr->serial);
@@ -3870,6 +3903,23 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
3870 sizeof(err_str)); 3903 sizeof(err_str));
3871} 3904}
3872 3905
3906/*
3907 * Handle a protocol violation when the parameter length is invalid.
3908 * "Invalid" length is identified as smaller then the minimal length a
3909 * given parameter can be.
3910 */
3911static sctp_disposition_t sctp_sf_violation_paramlen(
3912 const struct sctp_endpoint *ep,
3913 const struct sctp_association *asoc,
3914 const sctp_subtype_t type,
3915 void *arg,
3916 sctp_cmd_seq_t *commands) {
3917 char err_str[] = "The following parameter had invalid length:";
3918
3919 return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
3920 sizeof(err_str));
3921}
3922
3873/* Handle a protocol violation when the peer trying to advance the 3923/* Handle a protocol violation when the peer trying to advance the
3874 * cumulative tsn ack to a point beyond the max tsn currently sent. 3924 * cumulative tsn ack to a point beyond the max tsn currently sent.
3875 * 3925 *