diff mbox

Possible NULL dereference caused by -stable commit ef81bb40bf15f350fe865f31fa42f1082772a576

Message ID 4E82FC4E.5010101@redhat.com
State Superseded, archived
Delegated to: David Miller
Headers show

Commit Message

Jason Wang Sept. 28, 2011, 10:51 a.m. UTC
Hi all:

A possible NULL dereference were noticed by the stable commit 
ef81bb40bf15f350fe865f31fa42f1082772a576 (which is a backport of 
87c48fa3b4630905f98268dde838ee43626a060c). The case happens when bridge 
froward a packet from guest to a physical nic, at this time no route is 
attached to the skb which may lead a NULL dereference in 
ipv6_select_ident(). -Next version have this check so it is fine. The 
following patch may be used to avoid this but may also lead the ip 
identification predicable, and this defect is also exist -next version 
when no route because we still depends on a global variable to generate 
the identification.  Any thought on this?

Thanks.


  int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Eric Dumazet Sept. 28, 2011, 12:09 p.m. UTC | #1
Le mercredi 28 septembre 2011 à 18:51 +0800, Jason Wang a écrit :
> Hi all:
> 
> A possible NULL dereference were noticed by the stable commit 
> ef81bb40bf15f350fe865f31fa42f1082772a576 (which is a backport of 
> 87c48fa3b4630905f98268dde838ee43626a060c). The case happens when bridge 
> froward a packet from guest to a physical nic, at this time no route is 
> attached to the skb which may lead a NULL dereference in 
> ipv6_select_ident(). -Next version have this check so it is fine. The 
> following patch may be used to avoid this but may also lead the ip 
> identification predicable, and this defect is also exist -next version 
> when no route because we still depends on a global variable to generate 
> the identification.  Any thought on this?

1) Discussion on current kernel :

All we need here is not the route but inet_peer, so that inet_getid()
can be called on it.

If no route is given to ipv6_select_ident(), at least we can try to get
inet_peer, and release it before exiting from ipv6_select_ident()

2) On stable kernel, we already use an array
(ipv6_fragmentation_id[FID_HASH_SZ];) to make less predictables
fragments ids.

So we could get dst addr from the packet to be forwarded instead of the
(possibly NULL) route.



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller Sept. 28, 2011, 5:12 p.m. UTC | #2
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 28 Sep 2011 14:09:09 +0200

> All we need here is not the route but inet_peer, so that inet_getid()
> can be called on it.

It's not exactly that simple, you have to parse all hop-by-hop options
to get the correct "destination" address.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller Sept. 28, 2011, 6:32 p.m. UTC | #3
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 28 Sep 2011 14:09:09 +0200

> 1) Discussion on current kernel :
> 
> All we need here is not the route but inet_peer, so that inet_getid()
> can be called on it.
> 
> If no route is given to ipv6_select_ident(), at least we can try to get
> inet_peer, and release it before exiting from ipv6_select_ident()

Ok, after some auditing, there is only one call site of ipv6_select_ident()
that can happen with a NULL route and that is udp6_ufo_fragment().

ipv6_gso_segment() already walks the extension headers via
ipv6_gso_pull_exthdrs() so maybe we can calculate the true destination
address there and get that passed down somehow into the fragment ID
selection for an inetpeer lookup.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4ea6e21..414e2f4 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -622,7 +622,9 @@  static u32 __ipv6_select_ident(const struct in6_addr 
*addr)

  void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
  {
-       fhdr->identification = 
htonl(__ipv6_select_ident(&rt->rt6i_dst.addr));
+       const struct in6_addr addr = IN6ADDR_ANY_INIT;
+       fhdr->identification =
+               htonl(__ipv6_select_ident(rt ? &rt->rt6i_dst.addr : &addr));
  }