From d60ce6a6940af03ff5219d6d33087f1d8f9e35e7 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 19 Jun 2008 16:07:48 -0700 Subject: [PATCH] --- yaml --- r: 103067 b: refs/heads/master c: 7115e632f90952454ab6426e0d2151327162a30f h: refs/heads/master i: 103065: a7ef53a331c63ce4e58e3ae9da892aa2e458ce23 103063: 61e617c217fefc09d87bf53564d2388c07e58ad4 v: v3 --- [refs] | 2 +- trunk/net/sctp/input.c | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index 71a9cd7354e2..baa85447967b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0344f1c66b544609e867bd24aa7bfa789dfa9830 +refs/heads/master: 7115e632f90952454ab6426e0d2151327162a30f diff --git a/trunk/net/sctp/input.c b/trunk/net/sctp/input.c index ca6b022b1df2..d354a23972d4 100644 --- a/trunk/net/sctp/input.c +++ b/trunk/net/sctp/input.c @@ -430,6 +430,9 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, struct sock *sk = NULL; struct sctp_association *asoc; struct sctp_transport *transport = NULL; + struct sctp_init_chunk *chunkhdr; + __u32 vtag = ntohl(sctphdr->vtag); + int len = skb->len - ((void *)sctphdr - (void *)skb->data); *app = NULL; *tpp = NULL; @@ -451,8 +454,28 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, sk = asoc->base.sk; - if (ntohl(sctphdr->vtag) != asoc->c.peer_vtag) { - ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); + /* RFC 4960, Appendix C. ICMP Handling + * + * ICMP6) An implementation MUST validate that the Verification Tag + * contained in the ICMP message matches the Verification Tag of + * the peer. If the Verification Tag is not 0 and does NOT + * match, discard the ICMP message. If it is 0 and the ICMP + * message contains enough bytes to verify that the chunk type is + * an INIT chunk and that the Initiate Tag matches the tag of the + * peer, continue with ICMP7. If the ICMP message is too short + * or the chunk type or the Initiate Tag does not match, silently + * discard the packet. + */ + if (vtag == 0) { + chunkhdr = (struct sctp_init_chunk *)((void *)sctphdr + + sizeof(struct sctphdr)); + if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t) + + sizeof(__be32) || + chunkhdr->chunk_hdr.type != SCTP_CID_INIT || + ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) { + goto out; + } + } else if (vtag != asoc->c.peer_vtag) { goto out; }