| From d7426c69a1942b2b9b709bf66b944ff09f561484 Mon Sep 17 00:00:00 2001 |
| From: WANG Cong <xiyou.wangcong@gmail.com> |
| Date: Wed, 8 Feb 2017 10:02:13 -0800 |
| Subject: [PATCH] sit: fix a double free on error path |
| |
| commit d7426c69a1942b2b9b709bf66b944ff09f561484 upstream. |
| |
| Dmitry reported a double free in sit_init_net(): |
| |
| kernel BUG at mm/percpu.c:689! |
| invalid opcode: 0000 [#1] SMP KASAN |
| Dumping ftrace buffer: |
| (ftrace buffer empty) |
| Modules linked in: |
| CPU: 0 PID: 15692 Comm: syz-executor1 Not tainted 4.10.0-rc6-next-20170206 #1 |
| Hardware name: Google Google Compute Engine/Google Compute Engine, |
| BIOS Google 01/01/2011 |
| task: ffff8801c9cc27c0 task.stack: ffff88017d1d8000 |
| RIP: 0010:pcpu_free_area+0x68b/0x810 mm/percpu.c:689 |
| RSP: 0018:ffff88017d1df488 EFLAGS: 00010046 |
| RAX: 0000000000010000 RBX: 00000000000007c0 RCX: ffffc90002829000 |
| RDX: 0000000000010000 RSI: ffffffff81940efb RDI: ffff8801db841d94 |
| RBP: ffff88017d1df590 R08: dffffc0000000000 R09: 1ffffffff0bb3bdd |
| R10: dffffc0000000000 R11: 00000000000135dd R12: ffff8801db841d80 |
| R13: 0000000000038e40 R14: 00000000000007c0 R15: 00000000000007c0 |
| FS: 00007f6ea608f700(0000) GS:ffff8801dbe00000(0000) knlGS:0000000000000000 |
| CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 |
| CR2: 000000002000aff8 CR3: 00000001c8d44000 CR4: 00000000001426f0 |
| DR0: 0000000020000000 DR1: 0000000020000000 DR2: 0000000000000000 |
| DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000600 |
| Call Trace: |
| free_percpu+0x212/0x520 mm/percpu.c:1264 |
| ipip6_dev_free+0x43/0x60 net/ipv6/sit.c:1335 |
| sit_init_net+0x3cb/0xa10 net/ipv6/sit.c:1831 |
| ops_init+0x10a/0x530 net/core/net_namespace.c:115 |
| setup_net+0x2ed/0x690 net/core/net_namespace.c:291 |
| copy_net_ns+0x26c/0x530 net/core/net_namespace.c:396 |
| create_new_namespaces+0x409/0x860 kernel/nsproxy.c:106 |
| unshare_nsproxy_namespaces+0xae/0x1e0 kernel/nsproxy.c:205 |
| SYSC_unshare kernel/fork.c:2281 [inline] |
| SyS_unshare+0x64e/0xfc0 kernel/fork.c:2231 |
| entry_SYSCALL_64_fastpath+0x1f/0xc2 |
| |
| This is because when tunnel->dst_cache init fails, we free dev->tstats |
| once in ipip6_tunnel_init() and twice in sit_init_net(). This looks |
| redundant but its ndo_uinit() does not seem enough to clean up everything |
| here. So avoid this by setting dev->tstats to NULL after the first free, |
| at least for -net. |
| |
| Reported-by: Dmitry Vyukov <dvyukov@google.com> |
| Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| |
| diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c |
| index fad992ad4bc8..99853c6e33a8 100644 |
| --- a/net/ipv6/sit.c |
| +++ b/net/ipv6/sit.c |
| @@ -1380,6 +1380,7 @@ static int ipip6_tunnel_init(struct net_device *dev) |
| err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); |
| if (err) { |
| free_percpu(dev->tstats); |
| + dev->tstats = NULL; |
| return err; |
| } |
| |
| -- |
| 2.12.0 |
| |