diff options
author | Martin KaFai Lau <kafai@fb.com> | 2015-10-15 19:39:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-16 03:39:16 -0400 |
commit | 0a1f59620068fb82a2e2aded202e62f4bb856d52 (patch) | |
tree | 34b1c01554617573d9da4389ff3c6955f677e6b4 | |
parent | ebfa45f0d952e5e7bb30a7f9daaad681de138728 (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.c | 20 |
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 | ||
251 | static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst, | ||
252 | unsigned long old) | ||
253 | { | ||
254 | return NULL; | ||
255 | } | ||
256 | |||
257 | static struct dst_ops ip6_dst_blackhole_ops = { | 251 | static 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)); |