Re: BUG: unable to handle kernel NULL pointer dereference in ipv6_select_ident

Chris Boot
2011-12-22T15:54:15Z

On 22/12/2011 14:15, Eric Dumazet wrote:
> Le jeudi 22 décembre 2011 à 10:04 +0000, Chris Boot a écrit :
>
>> Eric,
>>
>> So far so good. I've had this running for several hours this morning
>> with more of the prodding that would normally have crashed it, both IPv4
>> and IPv6, and it's holding up well.
>>
> Thanks for testing.
>
> Here is the official patch then (the .mtu() bit belongs to a separate
> patch)
>
> [PATCH] net: introduce DST_NOPEER dst flag
>
> Chris Boot reported crashes occurring in ipv6_select_ident().
>
> [ 461.457562] RIP: 0010:[<ffffffff812dde61>] [<ffffffff812dde61>]
> ipv6_select_ident+0x31/0xa7
>
> [ 461.578229] Call Trace:
> [ 461.580742]<IRQ>
> [ 461.582870] [<ffffffff812efa7f>] ? udp6_ufo_fragment+0x124/0x1a2
> [ 461.589054] [<ffffffff812dbfe0>] ? ipv6_gso_segment+0xc0/0x155
> [ 461.595140] [<ffffffff812700c6>] ? skb_gso_segment+0x208/0x28b
> [ 461.601198] [<ffffffffa03f236b>] ? ipv6_confirm+0x146/0x15e
> [nf_conntrack_ipv6]
> [ 461.608786] [<ffffffff81291c4d>] ? nf_iterate+0x41/0x77
> [ 461.614227] [<ffffffff81271d64>] ? dev_hard_start_xmit+0x357/0x543
> [ 461.620659] [<ffffffff81291cf6>] ? nf_hook_slow+0x73/0x111
> [ 461.626440] [<ffffffffa0379745>] ? br_parse_ip_options+0x19a/0x19a
> [bridge]
> [ 461.633581] [<ffffffff812722ff>] ? dev_queue_xmit+0x3af/0x459
> [ 461.639577] [<ffffffffa03747d2>] ? br_dev_queue_push_xmit+0x72/0x76
> [bridge]
> [ 461.646887] [<ffffffffa03791e3>] ? br_nf_post_routing+0x17d/0x18f
> [bridge]
> [ 461.653997] [<ffffffff81291c4d>] ? nf_iterate+0x41/0x77
> [ 461.659473] [<ffffffffa0374760>] ? br_flood+0xfa/0xfa [bridge]
> [ 461.665485] [<ffffffff81291cf6>] ? nf_hook_slow+0x73/0x111
> [ 461.671234] [<ffffffffa0374760>] ? br_flood+0xfa/0xfa [bridge]
> [ 461.677299] [<ffffffffa0379215>] ?
> nf_bridge_update_protocol+0x20/0x20 [bridge]
> [ 461.684891] [<ffffffffa03bb0e5>] ? nf_ct_zone+0xa/0x17 [nf_conntrack]
> [ 461.691520] [<ffffffffa0374760>] ? br_flood+0xfa/0xfa [bridge]
> [ 461.697572] [<ffffffffa0374812>] ? NF_HOOK.constprop.8+0x3c/0x56
> [bridge]
> [ 461.704616] [<ffffffffa0379031>] ?
> nf_bridge_push_encap_header+0x1c/0x26 [bridge]
> [ 461.712329] [<ffffffffa037929f>] ? br_nf_forward_finish+0x8a/0x95
> [bridge]
> [ 461.719490] [<ffffffffa037900a>] ?
> nf_bridge_pull_encap_header+0x1c/0x27 [bridge]
> [ 461.727223] [<ffffffffa0379974>] ? br_nf_forward_ip+0x1c0/0x1d4 [bridge]
> [ 461.734292] [<ffffffff81291c4d>] ? nf_iterate+0x41/0x77
> [ 461.739758] [<ffffffffa03748cc>] ? __br_deliver+0xa0/0xa0 [bridge]
> [ 461.746203] [<ffffffff81291cf6>] ? nf_hook_slow+0x73/0x111
> [ 461.751950] [<ffffffffa03748cc>] ? __br_deliver+0xa0/0xa0 [bridge]
> [ 461.758378] [<ffffffffa037533a>] ? NF_HOOK.constprop.4+0x56/0x56
> [bridge]
>
> This is caused by bridge netfilter special dst_entry (fake_rtable), a
> special shared entry, where attaching an inetpeer makes no sense.
>
> Problem is present since commit 87c48fa3b46 (ipv6: make fragment
> identifications less predictable)
>
> Introduce DST_NOPEER dst flag and make sure ipv6_select_ident() and
> __ip_select_ident() fallback to the 'no peer attached' handling.
>
> Reported-by: Chris Boot<bootc@bootc.net>
> Tested-by: Chris Boot<bootc@bootc.net>
> Signed-off-by: Eric Dumazet<eric.dumazet@gmail.com>
> ---
> include/net/dst.h | 1 +
> net/bridge/br_netfilter.c | 2 +-
> net/ipv4/route.c | 4 ++--
> net/ipv6/ip6_output.c | 2 +-
> 4 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/include/net/dst.h b/include/net/dst.h
> index 6faec1a..75766b4 100644
> --- a/include/net/dst.h
> +++ b/include/net/dst.h
> @@ -53,6 +53,7 @@ struct dst_entry {
> #define DST_NOHASH 0x0008
> #define DST_NOCACHE 0x0010
> #define DST_NOCOUNT 0x0020
> +#define DST_NOPEER 0x0040
>
> short error;
> short obsolete;
> diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
> index d6ec372..5693e5f 100644
> --- a/net/bridge/br_netfilter.c
> +++ b/net/bridge/br_netfilter.c
> @@ -141,7 +141,7 @@ void br_netfilter_rtable_init(struct net_bridge *br)
> rt->dst.dev = br->dev;
> rt->dst.path =&rt->dst;
> dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
> - rt->dst.flags = DST_NOXFRM;
> + rt->dst.flags = DST_NOXFRM | DST_NOPEER;
> rt->dst.ops =&fake_dst_ops;
> }
>
> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index 252c512..a5004f1 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -1366,7 +1366,7 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)
> {
> struct rtable *rt = (struct rtable *) dst;
>
> - if (rt) {
> + if (rt&& !(rt->dst.flags& DST_NOPEER)) {
> if (rt->peer == NULL)
> rt_bind_peer(rt, rt->rt_dst, 1);
>
> @@ -1377,7 +1377,7 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)
> iph->id = htons(inet_getid(rt->peer, more));
> return;
> }
> - } else
> + } else if (!rt)
> printk(KERN_DEBUG "rt_bind_peer(0) @%p\n",
> __builtin_return_address(0));
>
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 84d0bd5..ec56271 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -603,7 +603,7 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
> static atomic_t ipv6_fragmentation_id;
> int old, new;
>
> - if (rt) {
> + if (rt&& !(rt->dst.flags& DST_NOPEER)) {
> struct inet_peer *peer;
>
> if (!rt->rt6i_peer)
>
>

Eric,

I'm seeing a new problem now with IPv6 on my bridge, I don't know if
it's related to any of the patches you gave me.

Basically, I have eth0 and eth1 in a balance-rr bond (bond0), and this
is added as a port in a bridge. When the bond and bridge are freshly
brought up, IPv4 works fine but it appears to be deaf to IPv6 traffic.
It stays this way until I run 'tcpdump -i eth0' and 'tcpdump -i eth1'.
If I run tcpdump with the -p flag to not enable promiscuous mode, the
interfaces remain deaf. Only if they enter promiscuous mode do they
start to listen to each other. It also doesn't help to run tcpdump
against bond0 or br0 at all.

I'm not sure if once I've killed tcpdump they become deaf again, but I
have enough IPv6 traffic to keep the neighbour entry alive.

Cheers,
Chris

--
Chris Boot
bootc@bootc.net