Re: [PATCH net] netfilter: bridge: fix stale prevhdr pointer in br_ip6_fragment()

Florian Westphal <[email protected]>
Newsgroups gmane.comp.security.firewalls.netfilter.devel,gmane.linux.network,gmane.linux.kernel
Message-ID <[email protected]>
Xiang Mei (Microsoft) <[email protected]> wrote:
> br_ip6_fragment() gets prevhdr, a pointer into the skb head, from
> ip6_find_1stfragopt(), then calls skb_checksum_help().  For a cloned skb
> skb_checksum_help() reallocates the head via pskb_expand_head(), leaving
> prevhdr dangling.  It is later dereferenced in ip6_frag_next(), causing a
> use-after-free write.
> 
> Re-find prevhdr after skb_checksum_help() so it points into the current
> head.
> 
>   BUG: KASAN: slab-use-after-free in ip6_frag_next (net/ipv6/ip6_output.c:857)
>   Write of size 1 at addr ffff888013ff5016 by task exploit/141
>   Call Trace:
>    ...
>    kasan_report (mm/kasan/report.c:595)
>    ip6_frag_next (net/ipv6/ip6_output.c:857)
>    br_ip6_fragment (net/ipv6/netfilter.c:212)
>    nf_ct_bridge_post (net/bridge/netfilter/nf_conntrack_bridge.c:407)
>    nf_hook_slow (net/netfilter/core.c:619)
>    br_forward_finish (net/bridge/br_forward.c:66)
>    __br_forward (net/bridge/br_forward.c:115)
>    maybe_deliver (net/bridge/br_forward.c:191)
>    br_flood (net/bridge/br_forward.c:245)
>    br_handle_frame_finish (net/bridge/br_input.c:229)
>    br_handle_frame (net/bridge/br_input.c:442)
>    ...
>    packet_sendmsg (net/packet/af_packet.c:3114)
>    ...
>    do_syscall_64 (arch/x86/entry/syscall_64.c:94)
>    entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
>   Kernel panic - not syncing: Fatal exception in interrupt
> 
> Fixes: 764dd163ac92 ("netfilter: nf_conntrack_bridge: add support for IPv6")
> Reported-by: [email protected]
> Signed-off-by: Xiang Mei (Microsoft) <[email protected]>
> ---
>  net/ipv6/netfilter.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
> index 6d80f85e55fa..547879da9532 100644
> --- a/net/ipv6/netfilter.c
> +++ b/net/ipv6/netfilter.c
> @@ -147,6 +147,10 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
>  	    (err = skb_checksum_help(skb)))
>  		goto blackhole;
>  
> +	err = ip6_find_1stfragopt(skb, &prevhdr);
> +	if (err < 0)
> +		goto blackhole;

Would you mind sending a v2 that solves this the same way that it was
fixed in ipv6 output engine?

See
ef0efcd3bd3f ("ipv6: Fix dangling pointer when ipv6 fragment")

Thanks!
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.