On 3/9/07, David Miller <[EMAIL PROTECTED]> wrote:
> The whole cahce-multipath subsystem has to have it's guts revamped for
> proper error handling.

(Untested patch follows.)

From: Amit Choudhary <[EMAIL PROTECTED]>

Check the return value of kmalloc() in function wrandom_set_nhinfo(),
in file net/ipv4/multipath_wrandom.c.

[EMAIL PROTECTED]: return error status to caller.]
Signed-off-by: Amit Choudhary <[EMAIL PROTECTED]>
Signed-off-by: Pekka Enberg <[EMAIL PROTECTED]>
---
 include/net/ip_mp_alg.h      |    8 +++++---
 net/ipv4/multipath_wrandom.c |   19 +++++++++++++++----
 net/ipv4/route.c             |    9 +++++++--
 3 files changed, 27 insertions(+), 9 deletions(-)

Index: 2.6/include/net/ip_mp_alg.h
===================================================================
--- 2.6.orig/include/net/ip_mp_alg.h    2007-03-12 14:00:13.000000000 +0200
+++ 2.6/include/net/ip_mp_alg.h 2007-03-12 14:03:10.000000000 +0200
@@ -17,7 +17,7 @@ struct ip_mp_alg_ops {
        void    (*mp_alg_select_route)(const struct flowi *flp,
                                       struct rtable *rth, struct rtable **rp);
        void    (*mp_alg_flush)(void);
-       void    (*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
+       int     (*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
                                     unsigned char prefixlen,
                                     const struct fib_nh *nh);
        void    (*mp_alg_remove)(struct rtable *rth);
@@ -58,17 +58,19 @@ static inline void multipath_flush(void)
 #endif
 }
 
-static inline void multipath_set_nhinfo(struct rtable *rth,
+static inline int multipath_set_nhinfo(struct rtable *rth,
                                        __be32 network, __be32 netmask,
                                        unsigned char prefixlen,
                                        const struct fib_nh *nh)
 {
+       int err = 0;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
        struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
 
        if (ops && ops->mp_alg_set_nhinfo)
-               ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
+               err = ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
 #endif
+       return err;
 }
 
 static inline void multipath_remove(struct rtable *rth)
Index: 2.6/net/ipv4/multipath_wrandom.c
===================================================================
--- 2.6.orig/net/ipv4/multipath_wrandom.c       2007-03-12 14:00:33.000000000 
+0200
+++ 2.6/net/ipv4/multipath_wrandom.c    2007-03-12 14:02:17.000000000 +0200
@@ -216,14 +216,15 @@   last_power = 0;
        *rp = decision;
 }
 
-static void wrandom_set_nhinfo(__be32 network,
-                              __be32 netmask,
-                              unsigned char prefixlen,
-                              const struct fib_nh *nh)
+static int wrandom_set_nhinfo(__be32 network,
+                             __be32 netmask,
+                             unsigned char prefixlen,
+                             const struct fib_nh *nh)
 {
        const int state_idx = nh->nh_oif % MULTIPATH_STATE_SIZE;
        struct multipath_route *r, *target_route = NULL;
        struct multipath_dest *d, *target_dest = NULL;
+       int err = 0;
 
        /* store the weight information for a certain route */
        spin_lock_bh(&state[state_idx].lock);
@@ -240,6 +241,10 @@ static void wrandom_set_nhinfo(__be32 ne
                const size_t size_rt = sizeof(struct multipath_route);
                target_route = (struct multipath_route *)
                        kmalloc(size_rt, GFP_ATOMIC);
+               if (!target_route) {
+                       err = -ENOMEM;
+                       goto error;
+               }
 
                target_route->gw = nh->nh_gw;
                target_route->oif = nh->nh_oif;
@@ -262,6 +267,10 @@            memset(&target_route->rcu, 0, sizeof(s
                target_dest = (struct multipath_dest*)
                        kmalloc(size_dst, GFP_ATOMIC);
 
+               if (!target_dest) {
+                       err = -ENOMEM;
+                       goto error;
+               }
                target_dest->nh_info = nh;
                target_dest->network = network;
                target_dest->netmask = netmask;
@@ -275,6 +284,8 @@             memset(&target_dest->rcu, 0, sizeof(st
         */
 
        spin_unlock_bh(&state[state_idx].lock);
+  error:
+       return err;
 }
 
 static void __multipath_free(struct rcu_head *head)
Index: 2.6/net/ipv4/route.c
===================================================================
--- 2.6.orig/net/ipv4/route.c   2007-03-12 14:03:24.000000000 +0200
+++ 2.6/net/ipv4/route.c        2007-03-12 14:04:16.000000000 +0200
@@ -1880,11 +1880,13 @@         for (hop = 0; hop < hopcount; hop++) {
                        return err;
 
                /* forward hop information to multipath impl. */
-               multipath_set_nhinfo(rth,
+               err = multipath_set_nhinfo(rth,
                                     FIB_RES_NETWORK(*res),
                                     FIB_RES_NETMASK(*res),
                                     res->prefixlen,
                                     &FIB_RES_NH(*res));
+               if (err)
+                       return err;
        }
        skb->dst = &rtres->u.dst;
        return err;
@@ -2334,8 +2336,11 @@                  if (err != 0)
                                        oldflp->oif);
                        err = rt_intern_hash(hash, rth, rp);
 
+                       if (err != 0)
+                               goto cleanup;
+
                        /* forward hop information to multipath impl. */
-                       multipath_set_nhinfo(rth,
+                       err = multipath_set_nhinfo(rth,
                                             FIB_RES_NETWORK(*res),
                                             FIB_RES_NETMASK(*res),
                                             res->prefixlen,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to