aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_statefuns.c
diff options
context:
space:
mode:
authorWei Yongjun <yjwei@cn.fujitsu.com>2008-09-30 08:32:24 -0400
committerDavid S. Miller <davem@davemloft.net>2008-09-30 08:32:24 -0400
commitba0166708ef4da7eeb61dd92bbba4d5a749d6561 (patch)
tree0e28c1d17b67d24125df4f05cbcca94c7e90ccd3 /net/sctp/sm_statefuns.c
parent8b122efd13a227d35d5ca242561770db1b5e3658 (diff)
sctp: Fix kernel panic while process protocol violation parameter
Since call to function sctp_sf_abort_violation() need paramter 'arg' with 'struct sctp_chunk' type, it will read the chunk type and chunk length from the chunk_hdr member of chunk. But call to sctp_sf_violation_paramlen() always with 'struct sctp_paramhdr' type's parameter, it will be passed to sctp_sf_abort_violation(). This may cause kernel panic. sctp_sf_violation_paramlen() |-- sctp_sf_abort_violation() |-- sctp_make_abort_violation() This patch fixed this problem. This patch also fix two place which called sctp_sf_violation_paramlen() with wrong paramter type. 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>
Diffstat (limited to 'net/sctp/sm_statefuns.c')
-rw-r--r--net/sctp/sm_statefuns.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 8848d329aa2c..7c622af2ce55 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
119 const struct sctp_endpoint *ep, 119 const struct sctp_endpoint *ep,
120 const struct sctp_association *asoc, 120 const struct sctp_association *asoc,
121 const sctp_subtype_t type, 121 const sctp_subtype_t type,
122 void *arg, 122 void *arg, void *ext,
123 sctp_cmd_seq_t *commands); 123 sctp_cmd_seq_t *commands);
124 124
125static sctp_disposition_t sctp_sf_violation_ctsn( 125static sctp_disposition_t sctp_sf_violation_ctsn(
@@ -3425,7 +3425,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
3425 addr_param = (union sctp_addr_param *)hdr->params; 3425 addr_param = (union sctp_addr_param *)hdr->params;
3426 length = ntohs(addr_param->p.length); 3426 length = ntohs(addr_param->p.length);
3427 if (length < sizeof(sctp_paramhdr_t)) 3427 if (length < sizeof(sctp_paramhdr_t))
3428 return sctp_sf_violation_paramlen(ep, asoc, type, 3428 return sctp_sf_violation_paramlen(ep, asoc, type, arg,
3429 (void *)addr_param, commands); 3429 (void *)addr_param, commands);
3430 3430
3431 /* Verify the ASCONF chunk before processing it. */ 3431 /* Verify the ASCONF chunk before processing it. */
@@ -3433,8 +3433,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
3433 (sctp_paramhdr_t *)((void *)addr_param + length), 3433 (sctp_paramhdr_t *)((void *)addr_param + length),
3434 (void *)chunk->chunk_end, 3434 (void *)chunk->chunk_end,
3435 &err_param)) 3435 &err_param))
3436 return sctp_sf_violation_paramlen(ep, asoc, type, 3436 return sctp_sf_violation_paramlen(ep, asoc, type, arg,
3437 (void *)&err_param, commands); 3437 (void *)err_param, commands);
3438 3438
3439 /* ADDIP 5.2 E1) Compare the value of the serial number to the value 3439 /* ADDIP 5.2 E1) Compare the value of the serial number to the value
3440 * the endpoint stored in a new association variable 3440 * the endpoint stored in a new association variable
@@ -3542,8 +3542,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
3542 (sctp_paramhdr_t *)addip_hdr->params, 3542 (sctp_paramhdr_t *)addip_hdr->params,
3543 (void *)asconf_ack->chunk_end, 3543 (void *)asconf_ack->chunk_end,
3544 &err_param)) 3544 &err_param))
3545 return sctp_sf_violation_paramlen(ep, asoc, type, 3545 return sctp_sf_violation_paramlen(ep, asoc, type, arg,
3546 (void *)&err_param, commands); 3546 (void *)err_param, commands);
3547 3547
3548 if (last_asconf) { 3548 if (last_asconf) {
3549 addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; 3549 addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr;
@@ -4240,12 +4240,38 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
4240 const struct sctp_endpoint *ep, 4240 const struct sctp_endpoint *ep,
4241 const struct sctp_association *asoc, 4241 const struct sctp_association *asoc,
4242 const sctp_subtype_t type, 4242 const sctp_subtype_t type,
4243 void *arg, 4243 void *arg, void *ext,
4244 sctp_cmd_seq_t *commands) { 4244 sctp_cmd_seq_t *commands)
4245 static const char err_str[] = "The following parameter had invalid length:"; 4245{
4246 struct sctp_chunk *chunk = arg;
4247 struct sctp_paramhdr *param = ext;
4248 struct sctp_chunk *abort = NULL;
4246 4249
4247 return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, 4250 if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
4248 sizeof(err_str)); 4251 goto discard;
4252
4253 /* Make the abort chunk. */
4254 abort = sctp_make_violation_paramlen(asoc, chunk, param);
4255 if (!abort)
4256 goto nomem;
4257
4258 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
4259 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
4260
4261 sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
4262 SCTP_ERROR(ECONNABORTED));
4263 sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
4264 SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
4265 SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
4266
4267discard:
4268 sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
4269
4270 SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
4271
4272 return SCTP_DISPOSITION_ABORT;
4273nomem:
4274 return SCTP_DISPOSITION_NOMEM;
4249} 4275}
4250 4276
4251/* Handle a protocol violation when the peer trying to advance the 4277/* Handle a protocol violation when the peer trying to advance the