diff options
author | Wei Yongjun <yjwei@cn.fujitsu.com> | 2011-04-19 17:30:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-20 04:51:05 -0400 |
commit | de6becdc0844ff92b38ffd9f0c4db1d3de02835f (patch) | |
tree | f52df91a347ece7e4efc09ca2974e8e38f38a3f8 /net/sctp | |
parent | 85c5ed4e44a262344ce43b4bf23204107923ca95 (diff) |
sctp: fix to check the source address of COOKIE-ECHO chunk
SCTP does not check whether the source address of COOKIE-ECHO
chunk is the original address of INIT chunk or part of the any
address parameters saved in COOKIE in CLOSED state. So even if
the COOKIE-ECHO chunk is from any address but with correct COOKIE,
the COOKIE-ECHO chunk still be accepted. If the COOKIE is not from
a valid address, the assoc should not be established.
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')
-rw-r--r-- | net/sctp/sm_make_chunk.c | 26 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 3 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 14 |
3 files changed, 27 insertions, 16 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index f87ccb11a520..a7b65e9e44b3 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -2242,14 +2242,17 @@ int sctp_verify_init(const struct sctp_association *asoc, | |||
2242 | * Returns 0 on failure, else success. | 2242 | * Returns 0 on failure, else success. |
2243 | * FIXME: This is an association method. | 2243 | * FIXME: This is an association method. |
2244 | */ | 2244 | */ |
2245 | int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | 2245 | int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, |
2246 | const union sctp_addr *peer_addr, | 2246 | const union sctp_addr *peer_addr, |
2247 | sctp_init_chunk_t *peer_init, gfp_t gfp) | 2247 | sctp_init_chunk_t *peer_init, gfp_t gfp) |
2248 | { | 2248 | { |
2249 | union sctp_params param; | 2249 | union sctp_params param; |
2250 | struct sctp_transport *transport; | 2250 | struct sctp_transport *transport; |
2251 | struct list_head *pos, *temp; | 2251 | struct list_head *pos, *temp; |
2252 | struct sctp_af *af; | ||
2253 | union sctp_addr addr; | ||
2252 | char *cookie; | 2254 | char *cookie; |
2255 | int src_match = 0; | ||
2253 | 2256 | ||
2254 | /* We must include the address that the INIT packet came from. | 2257 | /* We must include the address that the INIT packet came from. |
2255 | * This is the only address that matters for an INIT packet. | 2258 | * This is the only address that matters for an INIT packet. |
@@ -2261,18 +2264,31 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
2261 | * added as the primary transport. The source address seems to | 2264 | * added as the primary transport. The source address seems to |
2262 | * be a a better choice than any of the embedded addresses. | 2265 | * be a a better choice than any of the embedded addresses. |
2263 | */ | 2266 | */ |
2264 | if (peer_addr) { | 2267 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) |
2265 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) | 2268 | goto nomem; |
2266 | goto nomem; | 2269 | |
2267 | } | 2270 | if (sctp_cmp_addr_exact(sctp_source(chunk), peer_addr)) |
2271 | src_match = 1; | ||
2268 | 2272 | ||
2269 | /* Process the initialization parameters. */ | 2273 | /* Process the initialization parameters. */ |
2270 | sctp_walk_params(param, peer_init, init_hdr.params) { | 2274 | sctp_walk_params(param, peer_init, init_hdr.params) { |
2275 | if (!src_match && (param.p->type == SCTP_PARAM_IPV4_ADDRESS || | ||
2276 | param.p->type == SCTP_PARAM_IPV6_ADDRESS)) { | ||
2277 | af = sctp_get_af_specific(param_type2af(param.p->type)); | ||
2278 | af->from_addr_param(&addr, param.addr, | ||
2279 | chunk->sctp_hdr->source, 0); | ||
2280 | if (sctp_cmp_addr_exact(sctp_source(chunk), &addr)) | ||
2281 | src_match = 1; | ||
2282 | } | ||
2271 | 2283 | ||
2272 | if (!sctp_process_param(asoc, param, peer_addr, gfp)) | 2284 | if (!sctp_process_param(asoc, param, peer_addr, gfp)) |
2273 | goto clean_up; | 2285 | goto clean_up; |
2274 | } | 2286 | } |
2275 | 2287 | ||
2288 | /* source address of chunk may not match any valid address */ | ||
2289 | if (!src_match) | ||
2290 | goto clean_up; | ||
2291 | |||
2276 | /* AUTH: After processing the parameters, make sure that we | 2292 | /* AUTH: After processing the parameters, make sure that we |
2277 | * have all the required info to potentially do authentications. | 2293 | * have all the required info to potentially do authentications. |
2278 | */ | 2294 | */ |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 3b80fe24dabf..d612ca1ca6c0 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -595,8 +595,7 @@ static int sctp_cmd_process_init(sctp_cmd_seq_t *commands, | |||
595 | * fail during INIT processing (due to malloc problems), | 595 | * fail during INIT processing (due to malloc problems), |
596 | * just return the error and stop processing the stack. | 596 | * just return the error and stop processing the stack. |
597 | */ | 597 | */ |
598 | if (!sctp_process_init(asoc, chunk->chunk_hdr->type, | 598 | if (!sctp_process_init(asoc, chunk, sctp_source(chunk), peer_init, gfp)) |
599 | sctp_source(chunk), peer_init, gfp)) | ||
600 | error = -ENOMEM; | 599 | error = -ENOMEM; |
601 | else | 600 | else |
602 | error = 0; | 601 | error = 0; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ad3b43bb75cc..ab949320468d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -393,8 +393,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
393 | goto nomem_init; | 393 | goto nomem_init; |
394 | 394 | ||
395 | /* The call, sctp_process_init(), can fail on memory allocation. */ | 395 | /* The call, sctp_process_init(), can fail on memory allocation. */ |
396 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 396 | if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), |
397 | sctp_source(chunk), | ||
398 | (sctp_init_chunk_t *)chunk->chunk_hdr, | 397 | (sctp_init_chunk_t *)chunk->chunk_hdr, |
399 | GFP_ATOMIC)) | 398 | GFP_ATOMIC)) |
400 | goto nomem_init; | 399 | goto nomem_init; |
@@ -725,7 +724,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
725 | */ | 724 | */ |
726 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; | 725 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; |
727 | 726 | ||
728 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 727 | if (!sctp_process_init(new_asoc, chunk, |
729 | &chunk->subh.cookie_hdr->c.peer_addr, | 728 | &chunk->subh.cookie_hdr->c.peer_addr, |
730 | peer_init, GFP_ATOMIC)) | 729 | peer_init, GFP_ATOMIC)) |
731 | goto nomem_init; | 730 | goto nomem_init; |
@@ -1464,8 +1463,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1464 | * Verification Tag and Peers Verification tag into a reserved | 1463 | * Verification Tag and Peers Verification tag into a reserved |
1465 | * place (local tie-tag and per tie-tag) within the state cookie. | 1464 | * place (local tie-tag and per tie-tag) within the state cookie. |
1466 | */ | 1465 | */ |
1467 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 1466 | if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), |
1468 | sctp_source(chunk), | ||
1469 | (sctp_init_chunk_t *)chunk->chunk_hdr, | 1467 | (sctp_init_chunk_t *)chunk->chunk_hdr, |
1470 | GFP_ATOMIC)) | 1468 | GFP_ATOMIC)) |
1471 | goto nomem; | 1469 | goto nomem; |
@@ -1694,8 +1692,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
1694 | */ | 1692 | */ |
1695 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; | 1693 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; |
1696 | 1694 | ||
1697 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 1695 | if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, |
1698 | sctp_source(chunk), peer_init, | ||
1699 | GFP_ATOMIC)) | 1696 | GFP_ATOMIC)) |
1700 | goto nomem; | 1697 | goto nomem; |
1701 | 1698 | ||
@@ -1780,8 +1777,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, | |||
1780 | * side effects--it is safe to run them here. | 1777 | * side effects--it is safe to run them here. |
1781 | */ | 1778 | */ |
1782 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; | 1779 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; |
1783 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 1780 | if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, |
1784 | sctp_source(chunk), peer_init, | ||
1785 | GFP_ATOMIC)) | 1781 | GFP_ATOMIC)) |
1786 | goto nomem; | 1782 | goto nomem; |
1787 | 1783 | ||