From ed759122f59b5e2739d1b1a7b49da501cc3ca534 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 24 Jul 2006 14:51:12 -0700 Subject: [PATCH] IP multicast route code was reusing an skb which could lead to use after free or double free. Signed-off-by: Stephen Hemminger --- net/ipv4/ipmr.c | 39 +++++++++++++++++++++++---------------- 1 files changed, 23 insertions(+), 16 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index ba33f86..5685945 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1580,32 +1580,39 @@ int ipmr_get_route(struct sk_buff *skb, cache = ipmr_cache_find(rt->rt_src, rt->rt_dst); if (cache==NULL) { + struct sk_buff *iskb; struct net_device *dev; int vif; if (nowait) { - read_unlock(&mrt_lock); - return -EAGAIN; + err = -EAGAIN; + goto out; } dev = skb->dev; if (dev == NULL || (vif = ipmr_find_vif(dev)) < 0) { - read_unlock(&mrt_lock); - return -ENODEV; + err = -ENODEV; + goto out; } - skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); - skb->nh.iph->ihl = sizeof(struct iphdr)>>2; - skb->nh.iph->saddr = rt->rt_src; - skb->nh.iph->daddr = rt->rt_dst; - skb->nh.iph->version = 0; - err = ipmr_cache_unresolved(vif, skb); - read_unlock(&mrt_lock); - return err; - } + + iskb = alloc_skb(sizeof(struct iphdr), GFP_KERNEL); + if (!iskb) { + err = -ENOMEM; + goto out; + } + memset(iskb->data, 0, sizeof(struct iphdr)); + iskb->nh.raw = iskb->data; + iskb->nh.iph->ihl = sizeof(struct iphdr)>>2; + iskb->nh.iph->saddr = rt->rt_src; + iskb->nh.iph->daddr = rt->rt_dst; - if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) - cache->mfc_flags |= MFC_NOTIFY; - err = ipmr_fill_mroute(skb, cache, rtm); + err = ipmr_cache_unresolved(vif, iskb); + } else { + if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) + cache->mfc_flags |= MFC_NOTIFY; + err = ipmr_fill_mroute(skb, cache, rtm); + } +out: read_unlock(&mrt_lock); return err; } -- 1.4.0