Message ID | 4E82FC4E.5010101@redhat.com |
---|---|
State | Superseded, archived |
Delegated to: | David Miller |
Headers | show |
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
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
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 --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)); }