aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-01-13 20:27:37 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-13 20:27:37 -0500
commit2570a4f5428bcdb1077622342181755741e7fa60 (patch)
treeb96fe3146042d5ada1172ec6fad6b661368313d2 /net/ipv6
parentba5b0bfa06b6fbee03c6889046e9adcefa5d2c20 (diff)
ipv6: skb_dst() can be NULL in ipv6_hop_jumbo().
This fixes CERT-FI FICORA #341748 Discovered by Olli Jarva and Tuomo Untinen from the CROSS project at Codenomicon Ltd. Just like in CVE-2007-4567, we can't rely upon skb_dst() being non-NULL at this point. We fixed that in commit e76b2b2567b83448c2ee85a896433b96150c92e6 ("[IPV6]: Do no rely on skb->dst before it is assigned.") However commit 483a47d2fe794328d29950fe00ce26dd405d9437 ("ipv6: added net argument to IP6_INC_STATS_BH") put a new version of the same bug into this function. Complicating analysis further, this bug can only trigger when network namespaces are enabled in the build. When namespaces are turned off, the dev_net() does not evaluate it's argument, so the dereference would not occur. So, for a long time, namespaces couldn't be turned on unless SYSFS was disabled. Therefore, this code has largely been disabled except by people turning it on explicitly for namespace development. With help from Eugene Teo <eugene@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/exthdrs.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index df159fffe4bc..4bac362b1335 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -559,6 +559,11 @@ static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
559 return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : __in6_dev_get(skb->dev); 559 return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : __in6_dev_get(skb->dev);
560} 560}
561 561
562static inline struct net *ipv6_skb_net(struct sk_buff *skb)
563{
564 return skb_dst(skb) ? dev_net(skb_dst(skb)->dev) : dev_net(skb->dev);
565}
566
562/* Router Alert as of RFC 2711 */ 567/* Router Alert as of RFC 2711 */
563 568
564static int ipv6_hop_ra(struct sk_buff *skb, int optoff) 569static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
@@ -580,8 +585,8 @@ static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
580static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) 585static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
581{ 586{
582 const unsigned char *nh = skb_network_header(skb); 587 const unsigned char *nh = skb_network_header(skb);
588 struct net *net = ipv6_skb_net(skb);
583 u32 pkt_len; 589 u32 pkt_len;
584 struct net *net = dev_net(skb_dst(skb)->dev);
585 590
586 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { 591 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
587 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", 592 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",