Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp587820ybt; Fri, 19 Jun 2020 08:47:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyt9fOZAfhRoGeDI98CoDzxPVRFtZUWxzdPiQFzgD/mqCbtRB0lqJAa3HYPoZPBnF7JdZ3L X-Received: by 2002:a17:906:1116:: with SMTP id h22mr4146635eja.350.1592581664378; Fri, 19 Jun 2020 08:47:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1592581664; cv=none; d=google.com; s=arc-20160816; b=ll7BBefC+/lpmUdfi/fzwXIeKi1Y70dyLlFlutUMRYxlMzobrpmUXu5MnOtLy+lUmE 1Zewm9OqQJ2dablXzNIrKOHHC5lB88jbnDJ8PPnpU6xiThN8tdJa8fH/+wslutna56Rg DOh+gSvou0f0EdUVewcI34Ddb9Giz3+wWnLrKNQtIwlnVSGewLsbj83SFOjQK3o7jkrT h7LehyKNEAWerFSESzUsfK/wV9EQMJLrKaWWRNzwdB1cf1a8gqz9ioaOxSslP+hllWoF 1ufrnkLr2WFTnEdbg1RMiwAx6EvudpZTOK0IHr+2t+NcQfjELoC3gW3S84ya+bIwENB0 zCug== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=CIodzb4ADgLYHLz/wqVVs7MIOM7KZCSgAMWcupd8418=; b=CyB5UWvkrx3GRSAg+PlNyRMvtZNTxBpwxEaXhEuimsGDKoPQNspV0WbLJIvO9C+8ml ow7a4gEAvTPpvv4GqqWtwCLQ5l997NXj5tIKTiwwn5VN17TZHIMbwoWPOmFU9OxHYnto J8t8PD6Uuujf0oBMOwD1JxnIDE1Um68gGmWag0xYXuzijarhA/0HpkXSz9XrSwh1W+5Q xewYervL3uNj9QINqO5EK0UKr4GFziTy1F258m0Y3/k/Y2OuiLGmDUE8b7GNoRxUtEPB vgabuWfu1CVp5DhFKS+tHCRsmhY5PPzKpXL9Sr1shxeRd+l0at8DxiHO701eG8etsoZn eHlg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=mJDb1mxA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id q8si4241011edn.403.2020.06.19.08.47.21; Fri, 19 Jun 2020 08:47:44 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=mJDb1mxA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404695AbgFSPoo (ORCPT + 99 others); Fri, 19 Jun 2020 11:44:44 -0400 Received: from mail.kernel.org ([198.145.29.99]:59620 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404423AbgFSP1t (ORCPT ); Fri, 19 Jun 2020 11:27:49 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DD4B720734; Fri, 19 Jun 2020 15:27:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1592580468; bh=jgH7W4uBhh0DiOYmPYpnZY92jnyyqhhICDrT5uPbnmg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mJDb1mxAVgQOa34HoO1qxxbL5HM/E8D+2x6UYOPJVGZwvo/pnbxKHQhAUDt24FPUF 3bhY2NvQquXQeD7vQ5s7maJ+TNiURzOfmsG2gefko+Fxend4DLgWlKqiTZQ6KmdizY nWHR42uAo5SS0/PCJol965BiVMho+wJlBve2qD3s= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Johannes Thumshirn , Qu Wenruo , David Sterba Subject: [PATCH 5.7 261/376] btrfs: reloc: fix reloc root leak and NULL pointer dereference Date: Fri, 19 Jun 2020 16:32:59 +0200 Message-Id: <20200619141722.682117523@linuxfoundation.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200619141710.350494719@linuxfoundation.org> References: <20200619141710.350494719@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Qu Wenruo commit 51415b6c1b117e223bc083e30af675cb5c5498f3 upstream. [BUG] When balance is canceled, there is a pretty high chance that unmounting the fs can lead to lead the NULL pointer dereference: BTRFS warning (device dm-3): page private not zero on page 223158272 ... BTRFS warning (device dm-3): page private not zero on page 223162368 BTRFS error (device dm-3): leaked root 18446744073709551608-304 refcount 1 BUG: kernel NULL pointer dereference, address: 0000000000000168 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 2 PID: 5793 Comm: umount Tainted: G O 5.7.0-rc5-custom+ #53 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 RIP: 0010:__lock_acquire+0x5dc/0x24c0 Call Trace: lock_acquire+0xab/0x390 _raw_spin_lock+0x39/0x80 btrfs_release_extent_buffer_pages+0xd7/0x200 [btrfs] release_extent_buffer+0xb2/0x170 [btrfs] free_extent_buffer+0x66/0xb0 [btrfs] btrfs_put_root+0x8e/0x130 [btrfs] btrfs_check_leaked_roots.cold+0x5/0x5d [btrfs] btrfs_free_fs_info+0xe5/0x120 [btrfs] btrfs_kill_super+0x1f/0x30 [btrfs] deactivate_locked_super+0x3b/0x80 deactivate_super+0x3e/0x50 cleanup_mnt+0x109/0x160 __cleanup_mnt+0x12/0x20 task_work_run+0x67/0xa0 exit_to_usermode_loop+0xc5/0xd0 syscall_return_slowpath+0x205/0x360 do_syscall_64+0x6e/0xb0 entry_SYSCALL_64_after_hwframe+0x49/0xb3 RIP: 0033:0x7fd028ef740b [CAUSE] When balance is canceled, all reloc roots are marked as orphan, and orphan reloc roots are going to be cleaned up. However for orphan reloc roots and merged reloc roots, their lifespan are quite different: Merged reloc roots | Orphan reloc roots by cancel -------------------------------------------------------------------- create_reloc_root() | create_reloc_root() |- refs == 1 | |- refs == 1 | btrfs_grab_root(reloc_root); | btrfs_grab_root(reloc_root); |- refs == 2 | |- refs == 2 | root->reloc_root = reloc_root; | root->reloc_root = reloc_root; >>> No difference so far <<< | prepare_to_merge() | prepare_to_merge() |- btrfs_set_root_refs(item, 1);| |- if (!err) (err == -EINTR) | merge_reloc_roots() | merge_reloc_roots() |- merge_reloc_root() | |- Doing nothing to put reloc root |- insert_dirty_subvol() | |- refs == 2 |- __del_reloc_root() | |- btrfs_put_root() | |- refs == 1 | >>> Now orphan reloc roots still have refs 2 <<< | clean_dirty_subvols() | clean_dirty_subvols() |- btrfs_drop_snapshot() | |- btrfS_drop_snapshot() |- reloc_root get freed | |- reloc_root still has refs 2 | related ebs get freed, but | reloc_root still recorded in | allocated_roots btrfs_check_leaked_roots() | btrfs_check_leaked_roots() |- No leaked roots | |- Leaked reloc_roots detected | |- btrfs_put_root() | |- free_extent_buffer(root->node); | |- eb already freed, caused NULL | pointer dereference [FIX] The fix is to clear fs_root->reloc_root and put it at merge_reloc_roots() time, so that we won't leak reloc roots. Fixes: d2311e698578 ("btrfs: relocation: Delay reloc tree deletion after merge_reloc_roots") CC: stable@vger.kernel.org # 5.1+ Tested-by: Johannes Thumshirn Signed-off-by: Qu Wenruo Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/relocation.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2624,12 +2624,10 @@ again: reloc_root = list_entry(reloc_roots.next, struct btrfs_root, root_list); + root = read_fs_root(fs_info, reloc_root->root_key.offset); if (btrfs_root_refs(&reloc_root->root_item) > 0) { - root = read_fs_root(fs_info, - reloc_root->root_key.offset); BUG_ON(IS_ERR(root)); BUG_ON(root->reloc_root != reloc_root); - ret = merge_reloc_root(rc, root); btrfs_put_root(root); if (ret) { @@ -2639,6 +2637,14 @@ again: goto out; } } else { + if (!IS_ERR(root)) { + if (root->reloc_root == reloc_root) { + root->reloc_root = NULL; + btrfs_put_root(reloc_root); + } + btrfs_put_root(root); + } + list_del_init(&reloc_root->root_list); /* Don't forget to queue this reloc root for cleanup */ list_add_tail(&reloc_root->reloc_dirty_list,