aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/mip6.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-09-25 16:01:28 -0400
committerDavid S. Miller <davem@davemloft.net>2012-09-25 16:04:44 -0400
commit96af69ea2a83d292238bdba20e4508ee967cf8cb (patch)
treebea3edef18f4817519b1084efd6e66c62d9a4f31 /net/ipv6/mip6.c
parent78cc88c408675a7cc42e6d7402c9d90080e0b841 (diff)
ipv6: mip6: fix mip6_mh_filter()
mip6_mh_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() Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/mip6.c')
-rw-r--r--net/ipv6/mip6.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 5b087c31d87b..0f9bdc5ee9f3 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -86,28 +86,30 @@ static int mip6_mh_len(int type)
86 86
87static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) 87static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
88{ 88{
89 struct ip6_mh *mh; 89 struct ip6_mh _hdr;
90 const struct ip6_mh *mh;
90 91
91 if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || 92 mh = skb_header_pointer(skb, skb_transport_offset(skb),
92 !pskb_may_pull(skb, (skb_transport_offset(skb) + 93 sizeof(_hdr), &_hdr);
93 ((skb_transport_header(skb)[1] + 1) << 3)))) 94 if (!mh)
94 return -1; 95 return -1;
95 96
96 mh = (struct ip6_mh *)skb_transport_header(skb); 97 if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len)
98 return -1;
97 99
98 if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { 100 if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
99 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", 101 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
100 mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); 102 mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
101 mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - 103 mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) +
102 skb_network_header(skb))); 104 skb_network_header_len(skb));
103 return -1; 105 return -1;
104 } 106 }
105 107
106 if (mh->ip6mh_proto != IPPROTO_NONE) { 108 if (mh->ip6mh_proto != IPPROTO_NONE) {
107 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", 109 LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
108 mh->ip6mh_proto); 110 mh->ip6mh_proto);
109 mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - 111 mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) +
110 skb_network_header(skb))); 112 skb_network_header_len(skb));
111 return -1; 113 return -1;
112 } 114 }
113 115