| From 67a9c94317402b826fc3db32afc8f39336803d97 Mon Sep 17 00:00:00 2001 |
| From: Taehee Yoo <ap420073@gmail.com> |
| Date: Fri, 9 Jul 2021 17:35:18 +0000 |
| Subject: net: validate lwtstate->data before returning from skb_tunnel_info() |
| |
| From: Taehee Yoo <ap420073@gmail.com> |
| |
| commit 67a9c94317402b826fc3db32afc8f39336803d97 upstream. |
| |
| skb_tunnel_info() returns pointer of lwtstate->data as ip_tunnel_info |
| type without validation. lwtstate->data can have various types such as |
| mpls_iptunnel_encap, etc and these are not compatible. |
| So skb_tunnel_info() should validate before returning that pointer. |
| |
| Splat looks like: |
| BUG: KASAN: slab-out-of-bounds in vxlan_get_route+0x418/0x4b0 [vxlan] |
| Read of size 2 at addr ffff888106ec2698 by task ping/811 |
| |
| CPU: 1 PID: 811 Comm: ping Not tainted 5.13.0+ #1195 |
| Call Trace: |
| dump_stack_lvl+0x56/0x7b |
| print_address_description.constprop.8.cold.13+0x13/0x2ee |
| ? vxlan_get_route+0x418/0x4b0 [vxlan] |
| ? vxlan_get_route+0x418/0x4b0 [vxlan] |
| kasan_report.cold.14+0x83/0xdf |
| ? vxlan_get_route+0x418/0x4b0 [vxlan] |
| vxlan_get_route+0x418/0x4b0 [vxlan] |
| [ ... ] |
| vxlan_xmit_one+0x148b/0x32b0 [vxlan] |
| [ ... ] |
| vxlan_xmit+0x25c5/0x4780 [vxlan] |
| [ ... ] |
| dev_hard_start_xmit+0x1ae/0x6e0 |
| __dev_queue_xmit+0x1f39/0x31a0 |
| [ ... ] |
| neigh_xmit+0x2f9/0x940 |
| mpls_xmit+0x911/0x1600 [mpls_iptunnel] |
| lwtunnel_xmit+0x18f/0x450 |
| ip_finish_output2+0x867/0x2040 |
| [ ... ] |
| |
| Fixes: 61adedf3e3f1 ("route: move lwtunnel state to dst_entry") |
| Signed-off-by: Taehee Yoo <ap420073@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/net/dst_metadata.h | 4 +++- |
| 1 file changed, 3 insertions(+), 1 deletion(-) |
| |
| --- a/include/net/dst_metadata.h |
| +++ b/include/net/dst_metadata.h |
| @@ -45,7 +45,9 @@ skb_tunnel_info(const struct sk_buff *sk |
| return &md_dst->u.tun_info; |
| |
| dst = skb_dst(skb); |
| - if (dst && dst->lwtstate) |
| + if (dst && dst->lwtstate && |
| + (dst->lwtstate->type == LWTUNNEL_ENCAP_IP || |
| + dst->lwtstate->type == LWTUNNEL_ENCAP_IP6)) |
| return lwt_tun_info(dst->lwtstate); |
| |
| return NULL; |