| From foo@baz Wed 29 Jul 2020 12:20:23 PM CEST |
| From: Wei Yongjun <weiyongjun1@huawei.com> |
| Date: Mon, 13 Jul 2020 23:59:50 +0800 |
| Subject: ip6_gre: fix null-ptr-deref in ip6gre_init_net() |
| |
| From: Wei Yongjun <weiyongjun1@huawei.com> |
| |
| [ Upstream commit 46ef5b89ec0ecf290d74c4aee844f063933c4da4 ] |
| |
| KASAN report null-ptr-deref error when register_netdev() failed: |
| |
| KASAN: null-ptr-deref in range [0x00000000000003c0-0x00000000000003c7] |
| CPU: 2 PID: 422 Comm: ip Not tainted 5.8.0-rc4+ #12 |
| Call Trace: |
| ip6gre_init_net+0x4ab/0x580 |
| ? ip6gre_tunnel_uninit+0x3f0/0x3f0 |
| ops_init+0xa8/0x3c0 |
| setup_net+0x2de/0x7e0 |
| ? rcu_read_lock_bh_held+0xb0/0xb0 |
| ? ops_init+0x3c0/0x3c0 |
| ? kasan_unpoison_shadow+0x33/0x40 |
| ? __kasan_kmalloc.constprop.0+0xc2/0xd0 |
| copy_net_ns+0x27d/0x530 |
| create_new_namespaces+0x382/0xa30 |
| unshare_nsproxy_namespaces+0xa1/0x1d0 |
| ksys_unshare+0x39c/0x780 |
| ? walk_process_tree+0x2a0/0x2a0 |
| ? trace_hardirqs_on+0x4a/0x1b0 |
| ? _raw_spin_unlock_irq+0x1f/0x30 |
| ? syscall_trace_enter+0x1a7/0x330 |
| ? do_syscall_64+0x1c/0xa0 |
| __x64_sys_unshare+0x2d/0x40 |
| do_syscall_64+0x56/0xa0 |
| entry_SYSCALL_64_after_hwframe+0x44/0xa9 |
| |
| ip6gre_tunnel_uninit() has set 'ign->fb_tunnel_dev' to NULL, later |
| access to ign->fb_tunnel_dev cause null-ptr-deref. Fix it by saving |
| 'ign->fb_tunnel_dev' to local variable ndev. |
| |
| Fixes: dafabb6590cb ("ip6_gre: fix use-after-free in ip6gre_tunnel_lookup()") |
| Reported-by: Hulk Robot <hulkci@huawei.com> |
| Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> |
| Reviewed-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv6/ip6_gre.c | 11 ++++++----- |
| 1 file changed, 6 insertions(+), 5 deletions(-) |
| |
| --- a/net/ipv6/ip6_gre.c |
| +++ b/net/ipv6/ip6_gre.c |
| @@ -1130,15 +1130,16 @@ static void ip6gre_destroy_tunnels(struc |
| static int __net_init ip6gre_init_net(struct net *net) |
| { |
| struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); |
| + struct net_device *ndev; |
| int err; |
| |
| - ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", |
| - NET_NAME_UNKNOWN, |
| - ip6gre_tunnel_setup); |
| - if (!ign->fb_tunnel_dev) { |
| + ndev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", |
| + NET_NAME_UNKNOWN, ip6gre_tunnel_setup); |
| + if (!ndev) { |
| err = -ENOMEM; |
| goto err_alloc_dev; |
| } |
| + ign->fb_tunnel_dev = ndev; |
| dev_net_set(ign->fb_tunnel_dev, net); |
| /* FB netdevice is special: we have one, and only one per netns. |
| * Allowing to move it to another netns is clearly unsafe. |
| @@ -1158,7 +1159,7 @@ static int __net_init ip6gre_init_net(st |
| return 0; |
| |
| err_reg_dev: |
| - ip6gre_dev_free(ign->fb_tunnel_dev); |
| + ip6gre_dev_free(ndev); |
| err_alloc_dev: |
| return err; |
| } |