diff options
author | Eric Dumazet <edumazet@google.com> | 2012-09-25 07:03:40 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-13 05:38:45 +0900 |
commit | 7a20f9c5fa76e602bf9dda7f610c8de04e7afa04 (patch) | |
tree | 967afe1eab6dc306c17e826392a2ddafe94bd2a0 /net | |
parent | 514ddfedb89c19c57de82aedec8da2bd8ff3802c (diff) | |
download | linux-stable-7a20f9c5fa76e602bf9dda7f610c8de04e7afa04.tar.gz linux-stable-7a20f9c5fa76e602bf9dda7f610c8de04e7afa04.tar.bz2 linux-stable-7a20f9c5fa76e602bf9dda7f610c8de04e7afa04.zip |
ipv6: raw: fix icmpv6_filter()
[ Upstream commit 1b05c4b50edbddbdde715c4a7350629819f6655e ]
icmpv6_filter() should not modify its input, or else its caller
would need to recompute ipv6_hdr() if skb->head is reallocated.
Use skb_header_pointer() instead of pskb_may_pull() and
change the prototype to make clear both sk and skb are const.
Also, if icmpv6 header cannot be found, do not deliver the packet,
as we do in IPv4.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/raw.c | 21 |
1 files changed, 10 insertions, 11 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5bddea778840..3ee28700de4c 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -107,21 +107,20 @@ found: * 0 - deliver * 1 - block */ -static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) +static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb) { - struct icmp6hdr *icmph; - struct raw6_sock *rp = raw6_sk(sk); - - if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) { - __u32 *data = &rp->filter.data[0]; - int bit_nr; + struct icmp6hdr *_hdr; + const struct icmp6hdr *hdr; - icmph = (struct icmp6hdr *) skb->data; - bit_nr = icmph->icmp6_type; + hdr = skb_header_pointer(skb, skb_transport_offset(skb), + sizeof(_hdr), &_hdr); + if (hdr) { + const __u32 *data = &raw6_sk(sk)->filter.data[0]; + unsigned int type = hdr->icmp6_type; - return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0; + return (data[type >> 5] & (1U << (type & 31))) != 0; } - return 0; + return 1; } #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |