From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794314788; b=P+TvRtpNghzIXCKjqU+6W3mddSJGgq5Eud6GFyFYoE9JLw9zyGk51Wga2oX1FgqJE7wc PgBLaY07LIaGtTO08ejanmvTK88lNBEO8n7NRJ842N9+Anh84mKfR8gH100L2vW3oSUly UJ9gvO3jizpxHEVHfAO9EzEIEJZ3wozxp88NPsjkmeZymW5CxRPXCU/WiNxsPuJpGZHkg 7+qk/V71AVlE1fgtEJ4CZg5fMCf2fJRMaIjOw8Y1b3Q3nBtd6DDNLcnbuN93m7SuesLpt j9R8Rc7ylYmsDqN0j4k/twdUg9la6N+CuT8HoZ6iEzxq/mLLNA61/guqVapn0hIlBgg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794314788; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=Qla8xyv8DUXCmaukEkS/7pXo2rsNQ2xe37S+9Sm7CDA=; b=5RY6C+4Fag0d338wrfWUQrR//5Lc8zhKFR3B3kXVwV+c0UZLl2IfA5grDW8i0mIPuAOF 4jQSvFZdVFdnvoJEv8G22wLwU+x0LMMRxwSegiz30JJsrhnyeiHZi8J2B3E/xyQlTh4uQ g9pbfArDzA9PhrNuZo3LyraJEZdzC/lm+IepzRndsMOvR9qOxFDlZidBiWrTT62K8tsYR ktHzKLHY/kZxFJFY/HjN8e1NiQ9apWecNqxzzNiDNFpxRMUhj3QuduajZf/3k+czIQ7Nw q9HwQUzjM8c9R3Fggi7kzfEXzMFSME715QphcFgW7BJ8Erx/2JbWmJXXkZRyPooHirw== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=IVVRiQ5C; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D652E606A32E for ; Tue, 10 Nov 2026 12:46:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=IVVRiQ5C Received: by smtp.kernel.org (Postfix) with ESMTPSA id 16B7B1F008AB; Tue, 10 Nov 2026 12:46:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1794314787; bh=Qla8xyv8DUXCmaukEkS/7pXo2rsNQ2xe37S+9Sm7CDA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=IVVRiQ5CR/Q3KDwGzhojpPkWCU9LK9T0n1UKWN178Aampy41y4E+ZJUYjBI8R9PCw 4MZU9Q75t1Lx36p/SXkvlXg+urBHi5WaBG1ZUdggY8pyf46p7K79dpv+7MPKxBCfzz fm4k/CmcLVrCrtQPSTSeI96GWkfVzQ0cXL7O3XAU7cILEXO2If92Js7WfjM/fFU0og tDpnOqHUp4wgkhN/jO+oSGPkNTSNfi3nyqTj9Snoq15zBVAnW2+Z5bFOrMunGmmHSC ocZVQrp+WgyQYWlEGTZ3jstycpjPSXHYgHz4bQ86VdLl0ubmXgiEquLlfE63NNDGCM xhmpKGoPNWuzA== From: Sasha Levin To: stable@vger.kernel.org Cc: Chao Yu , stable@kernel.org, Zhiguo Niu , Jaegeuk Kim , Sasha Levin Subject: [PATCH 7.3.y] f2fs: fix to avoid folio->mapping dereference in is_{meta, node}_folio() Date: Tue, 10 Nov 2026 07:46:24 -0500 Message-ID: <20261110124616.1470181-1-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261107050307-failed-7.3-b5a71253c5c7@kernel.org> References: <20261107050307-failed-7.3-b5a71253c5c7@kernel.org> X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Chao Yu [ Upstream commit b5a71253c5c7e1139eab2f3e1e13e0bf2cbcaac7 ] Otherwise, it may cause NULL pointer dereference in race condition: Thread A Thread B - f2fs_setattr - f2fs_truncate - f2fs_truncate_blocks - f2fs_do_truncate_blocks - f2fs_truncate_inode_blocks - truncate_dnode - truncate_node - invalidate_mapping_pages - folio->mapping = NULL - folio_lock - is_node_folio - F2FS_F_SB(folio): dereference on folio->mapping Cc: stable@kernel.org Fixes: 019a8912425e ("f2fs: introduce is_{meta,node}_folio") Reported-by: Zhiguo Niu Closes: https://lore.kernel.org/linux-f2fs-devel/c5d29b31-e764-4782-9639-be84b1b2bfc2@kernel.org Signed-off-by: Chao Yu Reviewed-by: Zhiguo Niu Signed-off-by: Jaegeuk Kim [ sashal: retained IS_DNODE(folio) and is_cold_node(folio) calls without the upstream sbi arguments ] Signed-off-by: Sasha Levin --- fs/f2fs/checkpoint.c | 4 ++-- fs/f2fs/data.c | 7 ++++--- fs/f2fs/f2fs.h | 10 +++++----- fs/f2fs/gc.c | 2 +- fs/f2fs/node.c | 20 ++++++++++---------- fs/f2fs/segment.c | 2 +- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 4b59f30ef45d5..794b1cb9221ef 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -291,7 +291,7 @@ static struct folio *__get_meta_folio(struct f2fs_sb_info *sbi, pgoff_t index, f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE); folio_lock(folio); - if (unlikely(!is_meta_folio(folio))) { + if (unlikely(!is_meta_folio(sbi, folio))) { f2fs_folio_put(folio, true); goto repeat; } @@ -638,7 +638,7 @@ long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, long nr_to_write, folio_lock(folio); - if (unlikely(!is_meta_folio(folio))) { + if (unlikely(!is_meta_folio(sbi, folio))) { continue_unlock: folio_unlock(folio); continue; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index cfd81bfc28a22..c161d8061e693 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -172,7 +172,8 @@ static void f2fs_finish_read_bio(struct bio *bio, bool in_task) dec_page_count(F2FS_F_SB(folio), __read_io_type(folio)); if (bio->bi_status == BLK_STS_OK && - F2FS_F_SB(folio)->node_inode && is_node_folio(folio) && + F2FS_F_SB(folio)->node_inode && + is_node_folio(F2FS_F_SB(folio), folio) && f2fs_sanity_check_node_footer(F2FS_F_SB(folio), folio, folio->index, NODE_TYPE_REGULAR, true)) bio->bi_status = BLK_STS_IOERR; @@ -359,12 +360,12 @@ static void f2fs_write_end_bio(struct bio *bio) } } - if (is_node_folio(folio)) { + if (is_node_folio(sbi, folio)) { f2fs_sanity_check_node_footer(sbi, folio, folio->index, NODE_TYPE_REGULAR, true); f2fs_bug_on(sbi, folio->index != nid_of_node(folio)); } - if (f2fs_in_warm_node_list(folio)) + if (f2fs_in_warm_node_list(sbi, folio)) f2fs_del_fsync_node_entry(sbi, folio); dec_page_count(sbi, type); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 0c85d90307f70..f0024647153dd 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2316,14 +2316,14 @@ static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi) return sbi->node_inode->i_mapping; } -static inline bool is_meta_folio(struct folio *folio) +static inline bool is_meta_folio(struct f2fs_sb_info *sbi, struct folio *folio) { - return folio->mapping == META_MAPPING(F2FS_F_SB(folio)); + return folio->mapping == META_MAPPING(sbi); } -static inline bool is_node_folio(struct folio *folio) +static inline bool is_node_folio(struct f2fs_sb_info *sbi, struct folio *folio) { - return folio->mapping == NODE_MAPPING(F2FS_F_SB(folio)); + return folio->mapping == NODE_MAPPING(sbi); } static inline bool is_sbi_flag_set(struct f2fs_sb_info *sbi, unsigned int type) @@ -3994,7 +3994,7 @@ enum node_type; int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid); bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type); -bool f2fs_in_warm_node_list(struct folio *folio); +bool f2fs_in_warm_node_list(struct f2fs_sb_info *sbi, struct folio *folio); void f2fs_init_fsync_node_info(struct f2fs_sb_info *sbi); void f2fs_del_fsync_node_entry(struct f2fs_sb_info *sbi, struct folio *folio); void f2fs_reset_fsync_node_info(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 0a00180c21dc2..738a5543f086a 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1429,7 +1429,7 @@ static int move_data_block(struct inode *inode, block_t bidx, F2FS_BLKSIZE); folio_lock(mfolio); - if (unlikely(!is_meta_folio(mfolio) || + if (unlikely(!is_meta_folio(fio.sbi, mfolio) || !folio_test_uptodate(mfolio))) { err = -EIO; f2fs_folio_put(mfolio, true); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 86c2e67e43b6a..b23fe1383009a 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -330,9 +330,9 @@ static unsigned int __gang_lookup_nat_set(struct f2fs_nm_info *nm_i, start, nr); } -bool f2fs_in_warm_node_list(struct folio *folio) +bool f2fs_in_warm_node_list(struct f2fs_sb_info *sbi, struct folio *folio) { - return is_node_folio(folio) && IS_DNODE(folio) && is_cold_node(folio); + return is_node_folio(sbi, folio) && IS_DNODE(folio) && is_cold_node(folio); } void f2fs_init_fsync_node_info(struct f2fs_sb_info *sbi) @@ -1290,7 +1290,7 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from) goto fail; if (offset[1] == 0 && get_nid(folio, offset[0], true)) { folio_lock(folio); - BUG_ON(!is_node_folio(folio)); + BUG_ON(!is_node_folio(sbi, folio)); set_nid(folio, offset[0], 0, true); folio_unlock(folio); } @@ -1605,7 +1605,7 @@ static struct folio *__get_node_folio(struct f2fs_sb_info *sbi, pgoff_t nid, folio_lock(folio); - if (unlikely(!is_node_folio(folio))) { + if (unlikely(!is_node_folio(sbi, folio))) { f2fs_folio_put(folio, true); goto repeat; } @@ -1724,7 +1724,7 @@ static struct folio *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino) folio_lock(folio); - if (unlikely(!is_node_folio(folio))) { + if (unlikely(!is_node_folio(sbi, folio))) { continue_unlock: folio_unlock(folio); continue; @@ -1834,7 +1834,7 @@ static bool __write_node_folio(struct folio *folio, bool atomic, bool do_fsync, f2fs_need_dentry_mark(sbi, ino_of_node(folio))); /* should add to global list before clearing PAGECACHE status */ - if (f2fs_in_warm_node_list(folio)) { + if (f2fs_in_warm_node_list(sbi, folio)) { seq = f2fs_add_fsync_node_entry(sbi, folio); if (seq_id) *seq_id = seq; @@ -1958,7 +1958,7 @@ int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, folio_lock(folio); - if (unlikely(!is_node_folio(folio))) { + if (unlikely(!is_node_folio(sbi, folio))) { continue_unlock: folio_unlock(folio); continue; @@ -2016,7 +2016,7 @@ int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, f2fs_debug(sbi, "Retry to write fsync mark: ino=%u, idx=%lx", ino, last_folio->index); folio_lock(last_folio); - if (unlikely(!is_node_folio(last_folio))) { + if (unlikely(!is_node_folio(sbi, last_folio))) { f2fs_folio_put(last_folio, true); ret = -EAGAIN; goto out; @@ -2094,7 +2094,7 @@ void f2fs_flush_inline_data(struct f2fs_sb_info *sbi) folio_lock(folio); - if (unlikely(!is_node_folio(folio))) + if (unlikely(!is_node_folio(sbi, folio))) goto unlock; if (!folio_test_dirty(folio)) goto unlock; @@ -2166,7 +2166,7 @@ int f2fs_sync_node_pages(struct f2fs_sb_info *sbi, else if (!folio_trylock(folio)) continue; - if (unlikely(!is_node_folio(folio))) { + if (unlikely(!is_node_folio(sbi, folio))) { continue_unlock: folio_unlock(folio); continue; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index f3a73b6c24c3f..09d044c6a166d 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -4158,7 +4158,7 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio) __func__, fio->ino, folio->index, type, fio->old_blkaddr, fio->new_blkaddr, err); folio_end_writeback(folio); - if (f2fs_in_warm_node_list(folio)) + if (f2fs_in_warm_node_list(fio->sbi, folio)) f2fs_del_fsync_node_entry(fio->sbi, folio); f2fs_bug_on(fio->sbi, !is_set_ckpt_flags(fio->sbi, CP_ERROR_FLAG)); -- 2.53.0