diff options
author | David S. Miller <davem@davemloft.net> | 2015-10-16 00:39:25 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-16 00:39:25 -0700 |
commit | 7de88271da98c0c6f918e4cf4aa214ac034bab00 (patch) | |
tree | 34b1c01554617573d9da4389ff3c6955f677e6b4 | |
parent | 53ca376eec4eb635e2249c8e89093f499e180731 (diff) | |
parent | 0a1f59620068fb82a2e2aded202e62f4bb856d52 (diff) |
Merge branch 'ipv6-blackhole-route-fix'
Martin KaFai Lau says:
====================
ipv6: Initialize rt6_info properly in ip6_blackhole_route()
This patchset ensures the rt6_info's fields are initialized properly
in ip6_blackhole_route() where xfrm_policy is the primarily user.
The first patch is a prep work. The second patch is the fix. It
fixes d52d3997f843 ("ipv6: Create percpu rt6_info").
Here is the oops reported by Phil Sutter <phil@nwl.cc>:
BUG: unable to handle kernel NULL pointer dereference at 00000000000000a0
IP: [<ffffffff8171a95e>] __ip6_datagram_connect+0x71e/0xa20
PGD c2cb1067 PUD c2d7a067 PMD 0
Oops: 0000 [#1] PREEMPT SMP
Modules linked in: cmac nfs lockd grace sunrpc bridge stp llc nvidia(PO) snd_usb_audio snd_usbmidi_lib iTCO_wdt
CPU: 1 PID: 2964 Comm: ping6 Tainted: P O 4.2.1-aufs #10
Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./4Core1333-Viiv, BIOS P1.60 07/01/2008
task: ffff8800ca62bc00 ti: ffff880129a14000 task.ti: ffff880129a14000
RIP: 0010:[<ffffffff8171a95e>] [<ffffffff8171a95e>] __ip6_datagram_connect+0x71e/0xa20
RSP: 0018:ffff880129a17da8 EFLAGS: 00010296
RAX: 000000000000000b RBX: 0000000000000000 RCX: 0000000000000006
RDX: 0000000000000007 RSI: 0000000000000246 RDI: ffff88012fc8d5a0
RBP: ffff8800cb9a9048 R08: 756e207369207472 R09: 216c6c756e207369
R10: 0000000000000665 R11: 0000000000000006 R12: ffff8800cb9a8cf8
R13: ffff8800cb9a8cf8 R14: 0000000000000000 R15: ffff8800cb9a8cc0
FS: 00007fb76ad74700(0000) GS:ffff88012fc80000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000000000a0 CR3: 00000000c2dba000 CR4: 00000000000406e0
Stack:
ffff8800cb9a9048 ffff8800cb9a8de0 ffff8800cb9feb70 ffffffff816b2c41
00007fb70000000b ffffea0000df7200 ffff8800cb9f5cfc ffff8800cb9a8cc0
03fffffffe068a20 ffff8800cb9a8cc0 ffffffff817097c0 0000000100000000
Call Trace:
[<ffffffff816b2c41>] ? udp_lib_get_port+0x1a1/0x380
[<ffffffff817097c0>] ? udpv6_rcv+0x20/0x20
[<ffffffff8171ac82>] ? ip6_datagram_connect+0x22/0x40
[<ffffffff8163ae9b>] ? SyS_connect+0x6b/0xb0
[<ffffffff810767ac>] ? __do_page_fault+0x15c/0x380
[<ffffffff8163a8d3>] ? SyS_socket+0x63/0xa0
[<ffffffff81741957>] ? entry_SYSCALL_64_fastpath+0x12/0x6a
Code: ba ae 00 00 00 48 c7 c6 7b 71 94 81 48 c7 c7 63 71 94 81 e8 6c 0f 02 00 48 85 db 75 0e 48 c7 c7 9f 71 94 81 31 c0 e8 59 0f 02 00 <48> 83 bb a0 00 00 00 00 75 0e 48 c7 c7 ae 71 94 81 31 c0 e8 41
RIP [<ffffffff8171a95e>] __ip6_datagram_connect+0x71e/0xa20
RSP <ffff880129a17da8>
CR2: 00000000000000a0
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/route.c | 37 |
1 files changed, 16 insertions, 21 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ed04e29a6aa3..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, { } -static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst, - unsigned long old) -{ - return NULL; -} - static struct dst_ops ip6_dst_blackhole_ops = { .family = AF_INET6, .destroy = ip6_dst_destroy, @@ -262,7 +256,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { .default_advmss = ip6_default_advmss, .update_pmtu = ip6_rt_blackhole_update_pmtu, .redirect = ip6_rt_blackhole_redirect, - .cow_metrics = ip6_rt_blackhole_cow_metrics, + .cow_metrics = dst_cow_metrics_generic, .neigh_lookup = ip6_neigh_lookup, }; @@ -319,6 +313,15 @@ static const struct rt6_info ip6_blk_hole_entry_template = { #endif +static void rt6_info_init(struct rt6_info *rt) +{ + struct dst_entry *dst = &rt->dst; + + memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); + INIT_LIST_HEAD(&rt->rt6i_siblings); + INIT_LIST_HEAD(&rt->rt6i_uncached); +} + /* allocate dst with ip6_dst_ops */ static struct rt6_info *__ip6_dst_alloc(struct net *net, struct net_device *dev, @@ -327,13 +330,9 @@ static struct rt6_info *__ip6_dst_alloc(struct net *net, struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0, DST_OBSOLETE_FORCE_CHK, flags); - if (rt) { - struct dst_entry *dst = &rt->dst; + if (rt) + rt6_info_init(rt); - memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); - INIT_LIST_HEAD(&rt->rt6i_siblings); - INIT_LIST_HEAD(&rt->rt6i_uncached); - } return rt; } @@ -1214,24 +1213,20 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0); if (rt) { - new = &rt->dst; - - memset(new + 1, 0, sizeof(*rt) - sizeof(*new)); + rt6_info_init(rt); + new = &rt->dst; new->__use = 1; new->input = dst_discard; new->output = dst_discard_sk; - if (dst_metrics_read_only(&ort->dst)) - new->_metrics = ort->dst._metrics; - else - dst_copy_metrics(new, &ort->dst); + dst_copy_metrics(new, &ort->dst); rt->rt6i_idev = ort->rt6i_idev; if (rt->rt6i_idev) in6_dev_hold(rt->rt6i_idev); rt->rt6i_gateway = ort->rt6i_gateway; - rt->rt6i_flags = ort->rt6i_flags; + rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU; rt->rt6i_metric = 0; memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); |