aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin KaFai Lau <kafai@fb.com>2015-10-15 19:39:58 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-16 03:39:16 -0400
commit0a1f59620068fb82a2e2aded202e62f4bb856d52 (patch)
tree34b1c01554617573d9da4389ff3c6955f677e6b4
parentebfa45f0d952e5e7bb30a7f9daaad681de138728 (diff)
ipv6: Initialize rt6_info properly in ip6_blackhole_route()
ip6_blackhole_route() does not initialize the newly allocated rt6_info properly. This patch: 1. Call rt6_info_init() to initialize rt6i_siblings and rt6i_uncached 2. The current rt->dst._metrics init code is incorrect: - 'rt->dst._metrics = ort->dst._metris' is not always safe - Not sure what dst_copy_metrics() is trying to do here considering ip6_rt_blackhole_cow_metrics() always returns NULL Fix: - Always do dst_copy_metrics() - Replace ip6_rt_blackhole_cow_metrics() with dst_cow_metrics_generic() 3. Mask out the RTF_PCPU bit from the newly allocated blackhole route. This bug triggers an oops (reported by Phil Sutter) in rt6_get_cookie(). It is because RTF_PCPU is set while rt->dst.from is NULL. Fixes: d52d3997f843 ("ipv6: Create percpu rt6_info") Signed-off-by: Martin KaFai Lau <kafai@fb.com> Reported-by: Phil Sutter <phil@nwl.cc> Tested-by: Phil Sutter <phil@nwl.cc> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org> Cc: Julian Anastasov <ja@ssi.bg> Cc: Phil Sutter <phil@nwl.cc> Cc: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/route.c20
1 files changed, 5 insertions, 15 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 4198017a5aa7..968f31c01f89 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -248,12 +248,6 @@ static void ip6_rt_blackhole_redirect(struct dst_entry *dst, struct sock *sk,
248{ 248{
249} 249}
250 250
251static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst,
252 unsigned long old)
253{
254 return NULL;
255}
256
257static struct dst_ops ip6_dst_blackhole_ops = { 251static struct dst_ops ip6_dst_blackhole_ops = {
258 .family = AF_INET6, 252 .family = AF_INET6,
259 .destroy = ip6_dst_destroy, 253 .destroy = ip6_dst_destroy,
@@ -262,7 +256,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
262 .default_advmss = ip6_default_advmss, 256 .default_advmss = ip6_default_advmss,
263 .update_pmtu = ip6_rt_blackhole_update_pmtu, 257 .update_pmtu = ip6_rt_blackhole_update_pmtu,
264 .redirect = ip6_rt_blackhole_redirect, 258 .redirect = ip6_rt_blackhole_redirect,
265 .cow_metrics = ip6_rt_blackhole_cow_metrics, 259 .cow_metrics = dst_cow_metrics_generic,
266 .neigh_lookup = ip6_neigh_lookup, 260 .neigh_lookup = ip6_neigh_lookup,
267}; 261};
268 262
@@ -1219,24 +1213,20 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
1219 1213
1220 rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0); 1214 rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0);
1221 if (rt) { 1215 if (rt) {
1222 new = &rt->dst; 1216 rt6_info_init(rt);
1223
1224 memset(new + 1, 0, sizeof(*rt) - sizeof(*new));
1225 1217
1218 new = &rt->dst;
1226 new->__use = 1; 1219 new->__use = 1;
1227 new->input = dst_discard; 1220 new->input = dst_discard;
1228 new->output = dst_discard_sk; 1221 new->output = dst_discard_sk;
1229 1222
1230 if (dst_metrics_read_only(&ort->dst)) 1223 dst_copy_metrics(new, &ort->dst);
1231 new->_metrics = ort->dst._metrics;
1232 else
1233 dst_copy_metrics(new, &ort->dst);
1234 rt->rt6i_idev = ort->rt6i_idev; 1224 rt->rt6i_idev = ort->rt6i_idev;
1235 if (rt->rt6i_idev) 1225 if (rt->rt6i_idev)
1236 in6_dev_hold(rt->rt6i_idev); 1226 in6_dev_hold(rt->rt6i_idev);
1237 1227
1238 rt->rt6i_gateway = ort->rt6i_gateway; 1228 rt->rt6i_gateway = ort->rt6i_gateway;
1239 rt->rt6i_flags = ort->rt6i_flags; 1229 rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU;
1240 rt->rt6i_metric = 0; 1230 rt->rt6i_metric = 0;
1241 1231
1242 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); 1232 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));