aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-02-15 22:03:45 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2015-02-16 11:00:48 -0500
commit78296c97ca1fd3b104f12e1f1fbc06c46635990b (patch)
treebb6b737655d6412e4fb49c0a746f743691e81a24 /net
parentcef9ed86ed62eeffcd017882278bbece32001f86 (diff)
netfilter: xt_socket: fix a stack corruption bug
As soon as extract_icmp6_fields() returns, its local storage (automatic variables) is deallocated and can be overwritten. Lets add an additional parameter to make sure storage is valid long enough. While we are at it, adds some const qualifiers. Signed-off-by: Eric Dumazet <edumazet@google.com> Fixes: b64c9256a9b76 ("tproxy: added IPv6 support to the socket match") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/xt_socket.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index 1ba67931eb1b..13332dbf291d 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -243,12 +243,13 @@ static int
243extract_icmp6_fields(const struct sk_buff *skb, 243extract_icmp6_fields(const struct sk_buff *skb,
244 unsigned int outside_hdrlen, 244 unsigned int outside_hdrlen,
245 int *protocol, 245 int *protocol,
246 struct in6_addr **raddr, 246 const struct in6_addr **raddr,
247 struct in6_addr **laddr, 247 const struct in6_addr **laddr,
248 __be16 *rport, 248 __be16 *rport,
249 __be16 *lport) 249 __be16 *lport,
250 struct ipv6hdr *ipv6_var)
250{ 251{
251 struct ipv6hdr *inside_iph, _inside_iph; 252 const struct ipv6hdr *inside_iph;
252 struct icmp6hdr *icmph, _icmph; 253 struct icmp6hdr *icmph, _icmph;
253 __be16 *ports, _ports[2]; 254 __be16 *ports, _ports[2];
254 u8 inside_nexthdr; 255 u8 inside_nexthdr;
@@ -263,12 +264,14 @@ extract_icmp6_fields(const struct sk_buff *skb,
263 if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK) 264 if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK)
264 return 1; 265 return 1;
265 266
266 inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph); 267 inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph),
268 sizeof(*ipv6_var), ipv6_var);
267 if (inside_iph == NULL) 269 if (inside_iph == NULL)
268 return 1; 270 return 1;
269 inside_nexthdr = inside_iph->nexthdr; 271 inside_nexthdr = inside_iph->nexthdr;
270 272
271 inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), 273 inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) +
274 sizeof(*ipv6_var),
272 &inside_nexthdr, &inside_fragoff); 275 &inside_nexthdr, &inside_fragoff);
273 if (inside_hdrlen < 0) 276 if (inside_hdrlen < 0)
274 return 1; /* hjm: Packet has no/incomplete transport layer headers. */ 277 return 1; /* hjm: Packet has no/incomplete transport layer headers. */
@@ -315,10 +318,10 @@ xt_socket_get_sock_v6(struct net *net, const u8 protocol,
315static bool 318static bool
316socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) 319socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
317{ 320{
318 struct ipv6hdr *iph = ipv6_hdr(skb); 321 struct ipv6hdr ipv6_var, *iph = ipv6_hdr(skb);
319 struct udphdr _hdr, *hp = NULL; 322 struct udphdr _hdr, *hp = NULL;
320 struct sock *sk = skb->sk; 323 struct sock *sk = skb->sk;
321 struct in6_addr *daddr = NULL, *saddr = NULL; 324 const struct in6_addr *daddr = NULL, *saddr = NULL;
322 __be16 uninitialized_var(dport), uninitialized_var(sport); 325 __be16 uninitialized_var(dport), uninitialized_var(sport);
323 int thoff = 0, uninitialized_var(tproto); 326 int thoff = 0, uninitialized_var(tproto);
324 const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; 327 const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
@@ -342,7 +345,7 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
342 345
343 } else if (tproto == IPPROTO_ICMPV6) { 346 } else if (tproto == IPPROTO_ICMPV6) {
344 if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr, 347 if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
345 &sport, &dport)) 348 &sport, &dport, &ipv6_var))
346 return false; 349 return false;
347 } else { 350 } else {
348 return false; 351 return false;