diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-07 14:27:38 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-07 14:27:38 -0800 |
commit | 4c8237cd76a0510677dc2e3dd0f8866ec8e0b1e5 (patch) | |
tree | 09f2b802b5f493bfd5345ec808f3b58300cab168 | |
parent | 256ee435b9a9ee9cca69602fe8046b27ca99fbee (diff) | |
download | op-kernel-dev-4c8237cd76a0510677dc2e3dd0f8866ec8e0b1e5.zip op-kernel-dev-4c8237cd76a0510677dc2e3dd0f8866ec8e0b1e5.tar.gz |
ipv4: Validate route entry type at insert instead of every lookup.
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>
-rw-r--r-- | net/ipv4/fib_semantics.c | 54 |
1 files changed, 28 insertions, 26 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 562f34c..c29291b 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -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; } |