diff options
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 11 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_ah.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_frag.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_hbh.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_rt.c | 7 |
5 files changed, 31 insertions, 8 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index f0328c7bc1c9..53bf977cca63 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1440,6 +1440,9 @@ static void __exit ip6_tables_fini(void) * If target header is found, its offset is set in *offset and return protocol * number. Otherwise, return -1. * + * If the first fragment doesn't contain the final protocol header or + * NEXTHDR_NONE it is considered invalid. + * * Note that non-1st fragment is special case that "the protocol number * of last header" is "next header" field in Fragment header. In this case, * *offset is meaningless and fragment offset is stored in *fragoff if fragoff @@ -1463,12 +1466,12 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { if (target < 0) break; - return -1; + return -ENOENT; } hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); if (hp == NULL) - return -1; + return -EBADMSG; if (nexthdr == NEXTHDR_FRAGMENT) { unsigned short _frag_off, *fp; fp = skb_header_pointer(skb, @@ -1477,7 +1480,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, sizeof(_frag_off), &_frag_off); if (fp == NULL) - return -1; + return -EBADMSG; _frag_off = ntohs(*fp) & ~0x7; if (_frag_off) { @@ -1488,7 +1491,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, *fragoff = _frag_off; return hp->nexthdr; } - return -1; + return -ENOENT; } hdrlen = 8; } else if (nexthdr == NEXTHDR_AUTH) diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index ec1b1608156c..46486645eb75 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c @@ -54,9 +54,14 @@ match(const struct sk_buff *skb, const struct ip6t_ah *ahinfo = matchinfo; unsigned int ptr; unsigned int hdrlen = 0; + int err; - if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL) < 0) + err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); + if (err < 0) { + if (err != -ENOENT) + *hotdrop = 1; return 0; + } ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); if (ah == NULL) { diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 78d9c8b9e28a..cd22eaaccdca 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c @@ -52,9 +52,14 @@ match(const struct sk_buff *skb, struct frag_hdr _frag, *fh; const struct ip6t_frag *fraginfo = matchinfo; unsigned int ptr; + int err; - if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL) < 0) + err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); + if (err < 0) { + if (err != -ENOENT) + *hotdrop = 1; return 0; + } fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); if (fh == NULL) { diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index d32a205e3af2..3f25babe0440 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -65,9 +65,14 @@ match(const struct sk_buff *skb, u8 _opttype, *tp = NULL; u8 _optlen, *lp = NULL; unsigned int optlen; + int err; - if (ipv6_find_hdr(skb, &ptr, match->data, NULL) < 0) + err = ipv6_find_hdr(skb, &ptr, match->data, NULL); + if (err < 0) { + if (err != -ENOENT) + *hotdrop = 1; return 0; + } oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); if (oh == NULL) { diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index bcb2e168a5bc..54d7d14134fd 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -58,9 +58,14 @@ match(const struct sk_buff *skb, unsigned int hdrlen = 0; unsigned int ret = 0; struct in6_addr *ap, _addr; + int err; - if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL) < 0) + err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); + if (err < 0) { + if (err != -ENOENT) + *hotdrop = 1; return 0; + } rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); if (rh == NULL) { |