From: Huyen Nguyen <[EMAIL PROTECTED]>

A possible bug:

        rt_fill_info() calls ipmr_get_route().

          ipmr_get_route() calls ipmr_cache_unresolved()

            ipmr_cache_unresolved() gets an error and does kfree_skb(skb)

            ipmr_cache_unresolved() returns a -ve errno to ipmr_get_route()

          ipmr_get_route() returns the errno to rt_fill_info()

        rt_fill_info() diddles with the now-kfreed skb.

It may not be a bug if that kfree_skb() is only supposed to be balancing some
skb_get() which we didn't notice.  I don't think so, but could someone please
check?

Here's Huyen's proposed fix.  I think it goes halfway - it's clearer if the
function which takes a ref on a data structure is responsible for dropping
that ref too, rather than some two-deep callee.  IMO.

If we are going to deliberately do funky stuff like this then the skb lifetime
protocol should be commented, so as to avoid confusing poor little non-net
people.  IMO.

Signed-off-by: Huyen Nguyen <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
---

 net/ipv4/ipmr.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

diff -puN net/ipv4/ipmr.c~ipmr_cache_unresolved-fix net/ipv4/ipmr.c
--- devel/net/ipv4/ipmr.c~ipmr_cache_unresolved-fix     2006-03-25 
00:32:27.000000000 -0800
+++ devel-akpm/net/ipv4/ipmr.c  2006-03-25 00:32:27.000000000 -0800
@@ -641,8 +641,6 @@ ipmr_cache_unresolved(vifi_t vifi, struc
                if (atomic_read(&cache_resolve_queue_len)>=10 ||
                    (c=ipmr_cache_alloc_unres())==NULL) {
                        spin_unlock_bh(&mfc_unres_lock);
-
-                       kfree_skb(skb);
                        return -ENOBUFS;
                }
 
@@ -663,7 +661,6 @@ ipmr_cache_unresolved(vifi_t vifi, struc
                        spin_unlock_bh(&mfc_unres_lock);
 
                        kmem_cache_free(mrt_cachep, c);
-                       kfree_skb(skb);
                        return err;
                }
 
@@ -678,7 +675,6 @@ ipmr_cache_unresolved(vifi_t vifi, struc
         *      See if we can append the packet
         */
        if (c->mfc_un.unres.unresolved.qlen>3) {
-               kfree_skb(skb);
                err = -ENOBUFS;
        } else {
                skb_queue_tail(&c->mfc_un.unres.unresolved,skb);
@@ -1391,7 +1387,8 @@ int ip_mr_input(struct sk_buff *skb)
                if (vif >= 0) {
                        int err = ipmr_cache_unresolved(vif, skb);
                        read_unlock(&mrt_lock);
-
+                       if (err < 0)
+                               kfree_skb(skb);
                        return err;
                }
                read_unlock(&mrt_lock);
_
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to