net, bpf: Fix ip6ip6 crash with collect_md populated skbs
authorDaniel Borkmann <daniel@iogearbox.net>
Wed, 10 Mar 2021 00:38:10 +0000 (01:38 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 Mar 2021 12:32:05 +0000 (14:32 +0200)
commitc7eb3e12f18fc060d50d39c778e26929c5a0319f
tree632c30a1ffa6bd9b3db71a6c8458fc6d6ae3cece
parent0a245acbce8991668d5406f128f2c06a310c99a1
net, bpf: Fix ip6ip6 crash with collect_md populated skbs

[ Upstream commit a188bb5638d41aa99090ebf2f85d3505ab13fba5 ]

I ran into a crash where setting up a ip6ip6 tunnel device which was /not/
set to collect_md mode was receiving collect_md populated skbs for xmit.

The BPF prog was populating the skb via bpf_skb_set_tunnel_key() which is
assigning special metadata dst entry and then redirecting the skb to the
device, taking ip6_tnl_start_xmit() -> ipxip6_tnl_xmit() -> ip6_tnl_xmit()
and in the latter it performs a neigh lookup based on skb_dst(skb) where
we trigger a NULL pointer dereference on dst->ops->neigh_lookup() since
the md_dst_ops do not populate neigh_lookup callback with a fake handler.

Transform the md_dst_ops into generic dst_blackhole_ops that can also be
reused elsewhere when needed, and use them for the metadata dst entries as
callback ops.

Also, remove the dst_md_discard{,_out}() ops and rely on dst_discard{,_out}()
from dst_init() which free the skb the same way modulo the splat. Given we
will be able to recover just fine from there, avoid any potential splats
iff this gets ever triggered in future (or worse, panic on warns when set).

Fixes: f38a9eb1f77b ("dst: Metadata destinations")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/core/dst.c