ipv4: Validate route entry type at insert instead of every lookup.
authorDavid S. Miller <davem@davemloft.net>
Mon, 7 Mar 2011 22:27:38 +0000 (14:27 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 7 Mar 2011 22:27:38 +0000 (14:27 -0800)
fib_semantic_match() requires that if the type doesn't signal an
automatic error, it must be of type RTN_UNICAST, RTN_LOCAL,
RTN_BROADCAST, RTN_ANYCAST, or RTN_MULTICAST.

Checking this every route lookup is pointless work.

Instead validate it during route insertion, via fib_create_info().

Also, there was nothing making sure the type value was less than
RTN_MAX, so add that missing check while we're here.

Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/fib_semantics.c

index 562f34c..c29291b 100644 (file)
@@ -707,6 +707,9 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
        int nhs = 1;
        struct net *net = cfg->fc_nlinfo.nl_net;
 
+       if (cfg->fc_type > RTN_MAX)
+               goto err_inval;
+
        /* Fast check to catch the most weird cases */
        if (fib_props[cfg->fc_type].scope > cfg->fc_scope)
                goto err_inval;
@@ -812,6 +815,17 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
                if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
                        goto err_inval;
                goto link_it;
+       } else {
+               switch (cfg->fc_type) {
+               case RTN_UNICAST:
+               case RTN_LOCAL:
+               case RTN_BROADCAST:
+               case RTN_ANYCAST:
+               case RTN_MULTICAST:
+                       break;
+               default:
+                       goto err_inval;
+               }
        }
 
        if (cfg->fc_scope > RT_SCOPE_HOST)
@@ -915,35 +929,23 @@ int fib_semantic_match(struct fib_table *tb, struct list_head *head,
                        if (fi->fib_flags & RTNH_F_DEAD)
                                continue;
 
-                       switch (fa->fa_type) {
-                       case RTN_UNICAST:
-                       case RTN_LOCAL:
-                       case RTN_BROADCAST:
-                       case RTN_ANYCAST:
-                       case RTN_MULTICAST:
-                               for_nexthops(fi) {
-                                       if (nh->nh_flags & RTNH_F_DEAD)
-                                               continue;
-                                       if (!flp->oif || flp->oif == nh->nh_oif)
-                                               break;
-                               }
+                       for_nexthops(fi) {
+                               if (nh->nh_flags & RTNH_F_DEAD)
+                                       continue;
+                               if (!flp->oif || flp->oif == nh->nh_oif)
+                                       break;
+                       }
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-                               if (nhsel < fi->fib_nhs) {
-                                       nh_sel = nhsel;
-                                       goto out_fill_res;
-                               }
+                       if (nhsel < fi->fib_nhs) {
+                               nh_sel = nhsel;
+                               goto out_fill_res;
+                       }
 #else
-                               if (nhsel < 1)
-                                       goto out_fill_res;
+                       if (nhsel < 1)
+                               goto out_fill_res;
 #endif
-                               endfor_nexthops(fi);
-                               continue;
-
-                       default:
-                               pr_warning("fib_semantic_match bad type %#x\n",
-                                          fa->fa_type);
-                               return -EINVAL;
-                       }
+                       endfor_nexthops(fi);
+                       continue;
                }
                return err;
        }