Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp3730425pxb; Mon, 24 Jan 2022 16:33:42 -0800 (PST) X-Google-Smtp-Source: ABdhPJxsN2lCiGBZUmpEUa2NWMYRXUT4Ikxw1vOO9P2YDQkq0J4HWkOgamXRj94hPvRhzsGSdUm+ X-Received: by 2002:a17:903:18b:b0:14b:36be:e5aa with SMTP id z11-20020a170903018b00b0014b36bee5aamr10335831plg.94.1643070714438; Mon, 24 Jan 2022 16:31:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1643070714; cv=none; d=google.com; s=arc-20160816; b=H7Z2vgIVyHVfLiHlOUHQ6pSlva/KnDBbOn9O3Gwyfz6TWzBR727lerusedH593e6qx ve10v/o8l44kQVk7+AKtvmpik3SbORSGGAIFsXdD+K3K8EkwavMILMotkTWZ+xxeTar/ ci/8LdafbaWSMvWlDFFBAVW8MLOD5K3g9avZKFR9W64aPOxcvCITpdWl6/ku8nwbERNe 12z1dvmnClHgzw9F4DxW4SP2/VMNNdPbZTp3x49zVOK3opW5t568kv+jLqe729upuKSn Hj6C3POWB4GTqtmBXysOTrfVC2kTwnPZmEqRCcvfeebJUe9tCsa73vv5tZKIEwLYUeKZ 84Ow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=ctFRcvl0jjlILEDOD1fmYKsDcAzN+iwsJrqwbB+5ZKg=; b=qMCHenBq/BMg86a2Ay4EEMzy2GU0piIq8wz2dBObcAnhoOXIDSZN7FGdmKu0TUrXtZ ZyRRxZ3KMXCaUAwSlfD/Wna6GE9f8VLkj5y7ZJv4LA3cMXBIdzqYZ5NWoaVNuTs1RYt1 DyOBNjkHqqInq21JZ1MvSFmU1xV1fk7XzU+vmmt2UOLJf5xcM8A4MpqiS1kh19M7r1JI 1i2zgjiOQB9qCxlxHGXUu2uSkYQdPzHn51rUucqp/m38qPeUUY+RezYimou22wIxihw7 byfFoAFtBW2Pv80Sns4nK4ETzcVZj+ypwgeeHd9hh164JoYJvdgEX2WfYUP5y2rey+L+ 973g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=mu2eanA+; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id q189si5853607pgq.686.2022.01.24.16.31.42; Mon, 24 Jan 2022 16:31:54 -0800 (PST) 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=@linuxfoundation.org header.s=korg header.b=mu2eanA+; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S3410122AbiAYA2a (ORCPT + 99 others); Mon, 24 Jan 2022 19:28:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54932 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2360928AbiAXXin (ORCPT ); Mon, 24 Jan 2022 18:38:43 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 64D0CC0BD108; Mon, 24 Jan 2022 13:38:14 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 2D825B81243; Mon, 24 Jan 2022 21:38:13 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 570BBC340E5; Mon, 24 Jan 2022 21:38:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1643060291; bh=gQFqGG9/fSj/hQQshBDiTsv+zM3FhzzYSeDeoKFtb3U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mu2eanA+qdyNZbso2V/188c5zwXiudQrQao3H+FYuMc2OsNwkm3S5FwV4FlM1bvJd EssmELlECClO25TH4OeH7693hNnqj0J+UNj9NwxhxSjQSxWMepyKJoYJv3HbYaLRvr 71ZoAZ5twPVGY4/WWP8Mp1SPIaWPOPXy8LB9Iur4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Zhang Yi , Theodore Tso Subject: [PATCH 5.16 0900/1039] ext4: fix an use-after-free issue about data=journal writeback mode Date: Mon, 24 Jan 2022 19:44:49 +0100 Message-Id: <20220124184155.545115512@linuxfoundation.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220124184125.121143506@linuxfoundation.org> References: <20220124184125.121143506@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Zhang Yi commit 5c48a7df91499e371ef725895b2e2d21a126e227 upstream. Our syzkaller report an use-after-free issue that accessing the freed buffer_head on the writeback page in __ext4_journalled_writepage(). The problem is that if there was a truncate racing with the data=journalled writeback procedure, the writeback length could become zero and bget_one() refuse to get buffer_head's refcount, then the truncate procedure release buffer once we drop page lock, finally, the last ext4_walk_page_buffers() trigger the use-after-free problem. sync truncate ext4_sync_file() file_write_and_wait_range() ext4_setattr(0) inode->i_size = 0 ext4_writepage() len = 0 __ext4_journalled_writepage() page_bufs = page_buffers(page) ext4_walk_page_buffers(bget_one) <- does not get refcount do_invalidatepage() free_buffer_head() ext4_walk_page_buffers(page_bufs) <- trigger use-after-free After commit bdf96838aea6 ("ext4: fix race between truncate and __ext4_journalled_writepage()"), we have already handled the racing case, so the bget_one() and bput_one() are not needed. So this patch simply remove these hunk, and recheck the i_size to make it safe. Fixes: bdf96838aea6 ("ext4: fix race between truncate and __ext4_journalled_writepage()") Signed-off-by: Zhang Yi Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20211225090937.712867-1-yi.zhang@huawei.com Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1845,30 +1845,16 @@ int ext4_da_get_block_prep(struct inode return 0; } -static int bget_one(handle_t *handle, struct inode *inode, - struct buffer_head *bh) -{ - get_bh(bh); - return 0; -} - -static int bput_one(handle_t *handle, struct inode *inode, - struct buffer_head *bh) -{ - put_bh(bh); - return 0; -} - static int __ext4_journalled_writepage(struct page *page, unsigned int len) { struct address_space *mapping = page->mapping; struct inode *inode = mapping->host; - struct buffer_head *page_bufs = NULL; handle_t *handle = NULL; int ret = 0, err = 0; int inline_data = ext4_has_inline_data(inode); struct buffer_head *inode_bh = NULL; + loff_t size; ClearPageChecked(page); @@ -1878,14 +1864,6 @@ static int __ext4_journalled_writepage(s inode_bh = ext4_journalled_write_inline_data(inode, len, page); if (inode_bh == NULL) goto out; - } else { - page_bufs = page_buffers(page); - if (!page_bufs) { - BUG(); - goto out; - } - ext4_walk_page_buffers(handle, inode, page_bufs, 0, len, - NULL, bget_one); } /* * We need to release the page lock before we start the @@ -1906,7 +1884,8 @@ static int __ext4_journalled_writepage(s lock_page(page); put_page(page); - if (page->mapping != mapping) { + size = i_size_read(inode); + if (page->mapping != mapping || page_offset(page) > size) { /* The page got truncated from under us */ ext4_journal_stop(handle); ret = 0; @@ -1916,6 +1895,13 @@ static int __ext4_journalled_writepage(s if (inline_data) { ret = ext4_mark_inode_dirty(handle, inode); } else { + struct buffer_head *page_bufs = page_buffers(page); + + if (page->index == size >> PAGE_SHIFT) + len = size & ~PAGE_MASK; + else + len = PAGE_SIZE; + ret = ext4_walk_page_buffers(handle, inode, page_bufs, 0, len, NULL, do_journal_get_write_access); @@ -1936,9 +1922,6 @@ static int __ext4_journalled_writepage(s out: unlock_page(page); out_no_pagelock: - if (!inline_data && page_bufs) - ext4_walk_page_buffers(NULL, inode, page_bufs, 0, len, - NULL, bput_one); brelse(inode_bh); return ret; }