Commit 7de88271 authored by David S. Miller's avatar David S. Miller

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 d52d3997 ("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: default avatarDavid S. Miller <davem@davemloft.net>
parents 53ca376e 0a1f5962
...@@ -248,12 +248,6 @@ static void ip6_rt_blackhole_redirect(struct dst_entry *dst, struct sock *sk, ...@@ -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 = { static struct dst_ops ip6_dst_blackhole_ops = {
.family = AF_INET6, .family = AF_INET6,
.destroy = ip6_dst_destroy, .destroy = ip6_dst_destroy,
...@@ -262,7 +256,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { ...@@ -262,7 +256,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
.default_advmss = ip6_default_advmss, .default_advmss = ip6_default_advmss,
.update_pmtu = ip6_rt_blackhole_update_pmtu, .update_pmtu = ip6_rt_blackhole_update_pmtu,
.redirect = ip6_rt_blackhole_redirect, .redirect = ip6_rt_blackhole_redirect,
.cow_metrics = ip6_rt_blackhole_cow_metrics, .cow_metrics = dst_cow_metrics_generic,
.neigh_lookup = ip6_neigh_lookup, .neigh_lookup = ip6_neigh_lookup,
}; };
...@@ -319,6 +313,15 @@ static const struct rt6_info ip6_blk_hole_entry_template = { ...@@ -319,6 +313,15 @@ static const struct rt6_info ip6_blk_hole_entry_template = {
#endif #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 */ /* allocate dst with ip6_dst_ops */
static struct rt6_info *__ip6_dst_alloc(struct net *net, static struct rt6_info *__ip6_dst_alloc(struct net *net,
struct net_device *dev, struct net_device *dev,
...@@ -327,13 +330,9 @@ static struct rt6_info *__ip6_dst_alloc(struct net *net, ...@@ -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, struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
0, DST_OBSOLETE_FORCE_CHK, flags); 0, DST_OBSOLETE_FORCE_CHK, flags);
if (rt) { if (rt)
struct dst_entry *dst = &rt->dst; 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; return rt;
} }
...@@ -1214,24 +1213,20 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori ...@@ -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); rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0);
if (rt) { if (rt) {
new = &rt->dst; rt6_info_init(rt);
memset(new + 1, 0, sizeof(*rt) - sizeof(*new));
new = &rt->dst;
new->__use = 1; new->__use = 1;
new->input = dst_discard; new->input = dst_discard;
new->output = dst_discard_sk; new->output = dst_discard_sk;
if (dst_metrics_read_only(&ort->dst)) dst_copy_metrics(new, &ort->dst);
new->_metrics = ort->dst._metrics;
else
dst_copy_metrics(new, &ort->dst);
rt->rt6i_idev = ort->rt6i_idev; rt->rt6i_idev = ort->rt6i_idev;
if (rt->rt6i_idev) if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev); in6_dev_hold(rt->rt6i_idev);
rt->rt6i_gateway = ort->rt6i_gateway; rt->rt6i_gateway = ort->rt6i_gateway;
rt->rt6i_flags = ort->rt6i_flags; rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU;
rt->rt6i_metric = 0; rt->rt6i_metric = 0;
memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment