diff options
author | Sridhar Samudrala <sri@us.ibm.com> | 2005-07-18 16:44:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-07-18 16:44:10 -0400 |
commit | d1ad1ff299dd908d07c5e5f27f88bbdb235eb7a5 (patch) | |
tree | 03f66679f4a153ec06fde913907f392503f4b5e5 /net/sctp/input.c | |
parent | ee71a29eb5e341fe977c5ad7a43782c29bd9cb9e (diff) |
[SCTP]: Fix potential null pointer dereference while handling an icmp error
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/input.c')
-rw-r--r-- | net/sctp/input.c | 45 |
1 files changed, 12 insertions, 33 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index 5e085e041a6e..742be9171b7d 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -351,7 +351,6 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, | |||
351 | * | 351 | * |
352 | */ | 352 | */ |
353 | void sctp_icmp_proto_unreachable(struct sock *sk, | 353 | void sctp_icmp_proto_unreachable(struct sock *sk, |
354 | struct sctp_endpoint *ep, | ||
355 | struct sctp_association *asoc, | 354 | struct sctp_association *asoc, |
356 | struct sctp_transport *t) | 355 | struct sctp_transport *t) |
357 | { | 356 | { |
@@ -367,7 +366,6 @@ void sctp_icmp_proto_unreachable(struct sock *sk, | |||
367 | /* Common lookup code for icmp/icmpv6 error handler. */ | 366 | /* Common lookup code for icmp/icmpv6 error handler. */ |
368 | struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | 367 | struct sock *sctp_err_lookup(int family, struct sk_buff *skb, |
369 | struct sctphdr *sctphdr, | 368 | struct sctphdr *sctphdr, |
370 | struct sctp_endpoint **epp, | ||
371 | struct sctp_association **app, | 369 | struct sctp_association **app, |
372 | struct sctp_transport **tpp) | 370 | struct sctp_transport **tpp) |
373 | { | 371 | { |
@@ -375,11 +373,10 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
375 | union sctp_addr daddr; | 373 | union sctp_addr daddr; |
376 | struct sctp_af *af; | 374 | struct sctp_af *af; |
377 | struct sock *sk = NULL; | 375 | struct sock *sk = NULL; |
378 | struct sctp_endpoint *ep = NULL; | ||
379 | struct sctp_association *asoc = NULL; | 376 | struct sctp_association *asoc = NULL; |
380 | struct sctp_transport *transport = NULL; | 377 | struct sctp_transport *transport = NULL; |
381 | 378 | ||
382 | *app = NULL; *epp = NULL; *tpp = NULL; | 379 | *app = NULL; *tpp = NULL; |
383 | 380 | ||
384 | af = sctp_get_af_specific(family); | 381 | af = sctp_get_af_specific(family); |
385 | if (unlikely(!af)) { | 382 | if (unlikely(!af)) { |
@@ -394,26 +391,15 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
394 | * packet. | 391 | * packet. |
395 | */ | 392 | */ |
396 | asoc = __sctp_lookup_association(&saddr, &daddr, &transport); | 393 | asoc = __sctp_lookup_association(&saddr, &daddr, &transport); |
397 | if (!asoc) { | 394 | if (!asoc) |
398 | /* If there is no matching association, see if it matches any | 395 | return NULL; |
399 | * endpoint. This may happen for an ICMP error generated in | ||
400 | * response to an INIT_ACK. | ||
401 | */ | ||
402 | ep = __sctp_rcv_lookup_endpoint(&daddr); | ||
403 | if (!ep) { | ||
404 | return NULL; | ||
405 | } | ||
406 | } | ||
407 | 396 | ||
408 | if (asoc) { | 397 | sk = asoc->base.sk; |
409 | sk = asoc->base.sk; | ||
410 | 398 | ||
411 | if (ntohl(sctphdr->vtag) != asoc->c.peer_vtag) { | 399 | if (ntohl(sctphdr->vtag) != asoc->c.peer_vtag) { |
412 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 400 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); |
413 | goto out; | 401 | goto out; |
414 | } | 402 | } |
415 | } else | ||
416 | sk = ep->base.sk; | ||
417 | 403 | ||
418 | sctp_bh_lock_sock(sk); | 404 | sctp_bh_lock_sock(sk); |
419 | 405 | ||
@@ -423,7 +409,6 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
423 | if (sock_owned_by_user(sk)) | 409 | if (sock_owned_by_user(sk)) |
424 | NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS); | 410 | NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS); |
425 | 411 | ||
426 | *epp = ep; | ||
427 | *app = asoc; | 412 | *app = asoc; |
428 | *tpp = transport; | 413 | *tpp = transport; |
429 | return sk; | 414 | return sk; |
@@ -432,21 +417,16 @@ out: | |||
432 | sock_put(sk); | 417 | sock_put(sk); |
433 | if (asoc) | 418 | if (asoc) |
434 | sctp_association_put(asoc); | 419 | sctp_association_put(asoc); |
435 | if (ep) | ||
436 | sctp_endpoint_put(ep); | ||
437 | return NULL; | 420 | return NULL; |
438 | } | 421 | } |
439 | 422 | ||
440 | /* Common cleanup code for icmp/icmpv6 error handler. */ | 423 | /* Common cleanup code for icmp/icmpv6 error handler. */ |
441 | void sctp_err_finish(struct sock *sk, struct sctp_endpoint *ep, | 424 | void sctp_err_finish(struct sock *sk, struct sctp_association *asoc) |
442 | struct sctp_association *asoc) | ||
443 | { | 425 | { |
444 | sctp_bh_unlock_sock(sk); | 426 | sctp_bh_unlock_sock(sk); |
445 | sock_put(sk); | 427 | sock_put(sk); |
446 | if (asoc) | 428 | if (asoc) |
447 | sctp_association_put(asoc); | 429 | sctp_association_put(asoc); |
448 | if (ep) | ||
449 | sctp_endpoint_put(ep); | ||
450 | } | 430 | } |
451 | 431 | ||
452 | /* | 432 | /* |
@@ -471,7 +451,6 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
471 | int type = skb->h.icmph->type; | 451 | int type = skb->h.icmph->type; |
472 | int code = skb->h.icmph->code; | 452 | int code = skb->h.icmph->code; |
473 | struct sock *sk; | 453 | struct sock *sk; |
474 | struct sctp_endpoint *ep; | ||
475 | struct sctp_association *asoc; | 454 | struct sctp_association *asoc; |
476 | struct sctp_transport *transport; | 455 | struct sctp_transport *transport; |
477 | struct inet_sock *inet; | 456 | struct inet_sock *inet; |
@@ -488,7 +467,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
488 | savesctp = skb->h.raw; | 467 | savesctp = skb->h.raw; |
489 | skb->nh.iph = iph; | 468 | skb->nh.iph = iph; |
490 | skb->h.raw = (char *)sh; | 469 | skb->h.raw = (char *)sh; |
491 | sk = sctp_err_lookup(AF_INET, skb, sh, &ep, &asoc, &transport); | 470 | sk = sctp_err_lookup(AF_INET, skb, sh, &asoc, &transport); |
492 | /* Put back, the original pointers. */ | 471 | /* Put back, the original pointers. */ |
493 | skb->nh.raw = saveip; | 472 | skb->nh.raw = saveip; |
494 | skb->h.raw = savesctp; | 473 | skb->h.raw = savesctp; |
@@ -515,7 +494,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
515 | } | 494 | } |
516 | else { | 495 | else { |
517 | if (ICMP_PROT_UNREACH == code) { | 496 | if (ICMP_PROT_UNREACH == code) { |
518 | sctp_icmp_proto_unreachable(sk, ep, asoc, | 497 | sctp_icmp_proto_unreachable(sk, asoc, |
519 | transport); | 498 | transport); |
520 | goto out_unlock; | 499 | goto out_unlock; |
521 | } | 500 | } |
@@ -544,7 +523,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
544 | } | 523 | } |
545 | 524 | ||
546 | out_unlock: | 525 | out_unlock: |
547 | sctp_err_finish(sk, ep, asoc); | 526 | sctp_err_finish(sk, asoc); |
548 | } | 527 | } |
549 | 528 | ||
550 | /* | 529 | /* |