Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp106002yba; Mon, 20 May 2019 05:49:16 -0700 (PDT) X-Google-Smtp-Source: APXvYqx0dTs5SnP2qB4vtr8STb4y+/CxhKxZn5S77hFS6KjMcjKH3Z5cfDETkB50EjDlCBVX+Iic X-Received: by 2002:aa7:930e:: with SMTP id 14mr23039501pfj.262.1558356555993; Mon, 20 May 2019 05:49:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1558356555; cv=none; d=google.com; s=arc-20160816; b=nwDzWsdWd4nT8r60NKxag7Z3hTDW/uZcIYgpshIqpY2csbrLqPl5amfaYooZl9kz+8 r/FfDrGOMlZmX30mnIaWK5GFmBniDSwVzh5M8a+Y5TqTHqnwKQr9b0cD4LuFUgr0nzZc 1PGy4MgaHPIYZiHqzoZR5YGFHzluxxxI9S1P0++gVuvkJiopgYPQEWR+yOLWpwK87w5x LZu+OAj4TVvNyQi8byoU8sMQeHDFYyNke/9dFPRu0RZTrpH+DOCeTU8aOIfemXm5bf0Y +SnJvRxti5wqaxWezntjUESOG/e3gUat4BHFHuxxyPaNFvKfPgC8lUypPTec2bff9eaJ +CQA== 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=EanqRDvoNLF32ifMUpMtTBfkFwgrf0NGC16cKWaLAaY=; b=uYv45dL2fZttLSQa5uouRtmNeTkI7LyQaI3AntXFCsHukZOUE1t9xU2ploV9+lllDZ Rj100T5tv5meHKnXKV690H45fnM8jjk82lt0zeO+Vfu5yRFk1EobVUclAifF61OD7qbm 9zdxbNfh8eSXNTPU6LHWyea6Ys3aA9ef47H31LPWPsSb8tyy7Nkf8F0I/7zbh+9MNnq2 HH+QFIfNzAKdVPr2nOhwzzf6Z+96m8U06te/Yx+ky/IEBfjqOo6R/iM1TFXqlRf686Nx +LZBSI7jNGJaa/EjCisnvBECsdzW/GUF9tFqtrZND0qg4XycQz66g6UkfhqvSa5Jl288 wStA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=RWwDSf60; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v14si4005414pgk.117.2019.05.20.05.49.01; Mon, 20 May 2019 05:49:15 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=RWwDSf60; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388758AbfETMYH (ORCPT + 99 others); Mon, 20 May 2019 08:24:07 -0400 Received: from mail.kernel.org ([198.145.29.99]:38846 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388746AbfETMYD (ORCPT ); Mon, 20 May 2019 08:24:03 -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 535E921019; Mon, 20 May 2019 12:24:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1558355042; bh=ZyO2+CO4S/HcphVrzKwg2uGxCfCMMKt6+PAFr3DstdU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RWwDSf60aFu2hf+TvBuqrGEltWD1oOa0i53ecc1rVbUxxjyZOu4gQ+6Z9nlSm1rF/ 3MmyOqCya1IpVf0HM9mVCDqesmGAiMjFAZa4xpHmV6Bg5OooJwojWjPfXJ18JxvOeU 5y6AYAnX0ARC9v+7Oh3JHyWWUKDUxNQ2q8F30qKQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jungyeon , Nikolay Borisov , David Sterba Subject: [PATCH 4.19 074/105] btrfs: Correctly free extent buffer in case btree_read_extent_buffer_pages fails Date: Mon, 20 May 2019 14:14:20 +0200 Message-Id: <20190520115252.322297644@linuxfoundation.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190520115247.060821231@linuxfoundation.org> References: <20190520115247.060821231@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: Nikolay Borisov commit 537f38f019fa0b762dbb4c0fc95d7fcce9db8e2d upstream. If a an eb fails to be read for whatever reason - it's corrupted on disk and parent transid/key validations fail or IO for eb pages fail then this buffer must be removed from the buffer cache. Currently the code calls free_extent_buffer if an error occurs. Unfortunately this doesn't achieve the desired behavior since btrfs_find_create_tree_block returns with eb->refs == 2. On the other hand free_extent_buffer will only decrement the refs once leaving it added to the buffer cache radix tree. This enables later code to look up the buffer from the cache and utilize it potentially leading to a crash. The correct way to free the buffer is call free_extent_buffer_stale. This function will correctly call atomic_dec explicitly for the buffer and subsequently call release_extent_buffer which will decrement the final reference thus correctly remove the invalid buffer from buffer cache. This change affects only newly allocated buffers since they have eb->refs == 2. Link: https://bugzilla.kernel.org/show_bug.cgi?id=202755 Reported-by: Jungyeon CC: stable@vger.kernel.org # 4.4+ Signed-off-by: Nikolay Borisov Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/disk-io.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -995,13 +995,18 @@ void readahead_tree_block(struct btrfs_f { struct extent_buffer *buf = NULL; struct inode *btree_inode = fs_info->btree_inode; + int ret; buf = btrfs_find_create_tree_block(fs_info, bytenr); if (IS_ERR(buf)) return; - read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, - buf, WAIT_NONE, 0); - free_extent_buffer(buf); + + ret = read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, buf, + WAIT_NONE, 0); + if (ret < 0) + free_extent_buffer_stale(buf); + else + free_extent_buffer(buf); } int reada_tree_block_flagged(struct btrfs_fs_info *fs_info, u64 bytenr, @@ -1021,12 +1026,12 @@ int reada_tree_block_flagged(struct btrf ret = read_extent_buffer_pages(io_tree, buf, WAIT_PAGE_LOCK, mirror_num); if (ret) { - free_extent_buffer(buf); + free_extent_buffer_stale(buf); return ret; } if (test_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags)) { - free_extent_buffer(buf); + free_extent_buffer_stale(buf); return -EIO; } else if (extent_buffer_uptodate(buf)) { *eb = buf; @@ -1080,7 +1085,7 @@ struct extent_buffer *read_tree_block(st ret = btree_read_extent_buffer_pages(fs_info, buf, parent_transid, level, first_key); if (ret) { - free_extent_buffer(buf); + free_extent_buffer_stale(buf); return ERR_PTR(ret); } return buf;