All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chao Yu via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
To: jaegeuk@kernel.org
Cc: linux-kernel@vger.kernel.org,
	syzbot+b6b347b7a4ea1b2e29b6@syzkaller.appspotmail.com,
	linux-f2fs-devel@lists.sourceforge.net
Subject: Re: [f2fs-dev] [PATCH v2] f2fs: fix to avoid accessing uninitialized curseg
Date: Wed, 5 Mar 2025 17:16:25 +0800	[thread overview]
Message-ID: <9be24599-39de-4440-bd49-8f0629fa8a2b@kernel.org> (raw)
In-Reply-To: <20250224102923.93758-1-chao@kernel.org>

Jaegeuk, missed to check this patch?

On 2/24/25 18:29, Chao Yu wrote:
> syzbot reports a f2fs bug as below:
> 
> F2FS-fs (loop3): Stopped filesystem due to reason: 7
> kworker/u8:7: attempt to access beyond end of device
> BUG: unable to handle page fault for address: ffffed1604ea3dfa
> RIP: 0010:get_ckpt_valid_blocks fs/f2fs/segment.h:361 [inline]
> RIP: 0010:has_curseg_enough_space fs/f2fs/segment.h:570 [inline]
> RIP: 0010:__get_secs_required fs/f2fs/segment.h:620 [inline]
> RIP: 0010:has_not_enough_free_secs fs/f2fs/segment.h:633 [inline]
> RIP: 0010:has_enough_free_secs+0x575/0x1660 fs/f2fs/segment.h:649
>  <TASK>
>  f2fs_is_checkpoint_ready fs/f2fs/segment.h:671 [inline]
>  f2fs_write_inode+0x425/0x540 fs/f2fs/inode.c:791
>  write_inode fs/fs-writeback.c:1525 [inline]
>  __writeback_single_inode+0x708/0x10d0 fs/fs-writeback.c:1745
>  writeback_sb_inodes+0x820/0x1360 fs/fs-writeback.c:1976
>  wb_writeback+0x413/0xb80 fs/fs-writeback.c:2156
>  wb_do_writeback fs/fs-writeback.c:2303 [inline]
>  wb_workfn+0x410/0x1080 fs/fs-writeback.c:2343
>  process_one_work kernel/workqueue.c:3236 [inline]
>  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3317
>  worker_thread+0x870/0xd30 kernel/workqueue.c:3398
>  kthread+0x7a9/0x920 kernel/kthread.c:464
>  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:148
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> 
> Commit 8b10d3653735 ("f2fs: introduce FAULT_NO_SEGMENT") allows to trigger
> no free segment fault in allocator, then it will update curseg->segno to
> NULL_SEGNO, though, CP_ERROR_FLAG has been set, f2fs_write_inode() missed
> to check the flag, and access invalid curseg->segno directly in below call
> path, then resulting in panic:
> 
> - f2fs_write_inode
>  - f2fs_is_checkpoint_ready
>   - has_enough_free_secs
>    - has_not_enough_free_secs
>     - __get_secs_required
>      - has_curseg_enough_space
>       - get_ckpt_valid_blocks
>       : access invalid curseg->segno
> 
> To avoid this issue, let's:
> - check CP_ERROR_FLAG flag in prior to f2fs_is_checkpoint_ready() in
> f2fs_write_inode().
> - in has_curseg_enough_space(), save curseg->segno into a temp variable,
> and verify its validation before use.
> 
> Fixes: 8b10d3653735 ("f2fs: introduce FAULT_NO_SEGMENT")
> Reported-by: syzbot+b6b347b7a4ea1b2e29b6@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/67973c2b.050a0220.11b1bb.0089.GAE@google.com
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
> v2:
> - get rid of potential blocking on curseg_mutex
>  fs/f2fs/inode.c   | 7 +++++++
>  fs/f2fs/segment.h | 9 ++++++++-
>  2 files changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index d6ad7810df69..6aec752ac098 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -793,6 +793,13 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
>  		!is_inode_flag_set(inode, FI_DIRTY_INODE))
>  		return 0;
>  
> +	/*
> +	 * no need to update inode page, ultimately f2fs_evict_inode() will
> +	 * clear dirty status of inode.
> +	 */
> +	if (f2fs_cp_error(sbi))
> +		return -EIO;
> +
>  	if (!f2fs_is_checkpoint_ready(sbi)) {
>  		f2fs_mark_inode_dirty_sync(inode, true);
>  		return -ENOSPC;
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index 943be4f1d6d2..0465dc00b349 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -559,13 +559,16 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi,
>  			unsigned int node_blocks, unsigned int data_blocks,
>  			unsigned int dent_blocks)
>  {
> -
>  	unsigned int segno, left_blocks, blocks;
>  	int i;
>  
>  	/* check current data/node sections in the worst case. */
>  	for (i = CURSEG_HOT_DATA; i < NR_PERSISTENT_LOG; i++) {
>  		segno = CURSEG_I(sbi, i)->segno;
> +
> +		if (unlikely(segno == NULL_SEGNO))
> +			return false;
> +
>  		left_blocks = CAP_BLKS_PER_SEC(sbi) -
>  				get_ckpt_valid_blocks(sbi, segno, true);
>  
> @@ -576,6 +579,10 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi,
>  
>  	/* check current data section for dentry blocks. */
>  	segno = CURSEG_I(sbi, CURSEG_HOT_DATA)->segno;
> +
> +	if (unlikely(segno == NULL_SEGNO))
> +		return false;
> +
>  	left_blocks = CAP_BLKS_PER_SEC(sbi) -
>  			get_ckpt_valid_blocks(sbi, segno, true);
>  	if (dent_blocks > left_blocks)



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

WARNING: multiple messages have this Message-ID (diff)
From: Chao Yu <chao@kernel.org>
To: jaegeuk@kernel.org
Cc: chao@kernel.org, linux-f2fs-devel@lists.sourceforge.net,
	linux-kernel@vger.kernel.org,
	syzbot+b6b347b7a4ea1b2e29b6@syzkaller.appspotmail.com
Subject: Re: [PATCH v2] f2fs: fix to avoid accessing uninitialized curseg
Date: Wed, 5 Mar 2025 17:16:25 +0800	[thread overview]
Message-ID: <9be24599-39de-4440-bd49-8f0629fa8a2b@kernel.org> (raw)
In-Reply-To: <20250224102923.93758-1-chao@kernel.org>

Jaegeuk, missed to check this patch?

On 2/24/25 18:29, Chao Yu wrote:
> syzbot reports a f2fs bug as below:
> 
> F2FS-fs (loop3): Stopped filesystem due to reason: 7
> kworker/u8:7: attempt to access beyond end of device
> BUG: unable to handle page fault for address: ffffed1604ea3dfa
> RIP: 0010:get_ckpt_valid_blocks fs/f2fs/segment.h:361 [inline]
> RIP: 0010:has_curseg_enough_space fs/f2fs/segment.h:570 [inline]
> RIP: 0010:__get_secs_required fs/f2fs/segment.h:620 [inline]
> RIP: 0010:has_not_enough_free_secs fs/f2fs/segment.h:633 [inline]
> RIP: 0010:has_enough_free_secs+0x575/0x1660 fs/f2fs/segment.h:649
>  <TASK>
>  f2fs_is_checkpoint_ready fs/f2fs/segment.h:671 [inline]
>  f2fs_write_inode+0x425/0x540 fs/f2fs/inode.c:791
>  write_inode fs/fs-writeback.c:1525 [inline]
>  __writeback_single_inode+0x708/0x10d0 fs/fs-writeback.c:1745
>  writeback_sb_inodes+0x820/0x1360 fs/fs-writeback.c:1976
>  wb_writeback+0x413/0xb80 fs/fs-writeback.c:2156
>  wb_do_writeback fs/fs-writeback.c:2303 [inline]
>  wb_workfn+0x410/0x1080 fs/fs-writeback.c:2343
>  process_one_work kernel/workqueue.c:3236 [inline]
>  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3317
>  worker_thread+0x870/0xd30 kernel/workqueue.c:3398
>  kthread+0x7a9/0x920 kernel/kthread.c:464
>  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:148
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> 
> Commit 8b10d3653735 ("f2fs: introduce FAULT_NO_SEGMENT") allows to trigger
> no free segment fault in allocator, then it will update curseg->segno to
> NULL_SEGNO, though, CP_ERROR_FLAG has been set, f2fs_write_inode() missed
> to check the flag, and access invalid curseg->segno directly in below call
> path, then resulting in panic:
> 
> - f2fs_write_inode
>  - f2fs_is_checkpoint_ready
>   - has_enough_free_secs
>    - has_not_enough_free_secs
>     - __get_secs_required
>      - has_curseg_enough_space
>       - get_ckpt_valid_blocks
>       : access invalid curseg->segno
> 
> To avoid this issue, let's:
> - check CP_ERROR_FLAG flag in prior to f2fs_is_checkpoint_ready() in
> f2fs_write_inode().
> - in has_curseg_enough_space(), save curseg->segno into a temp variable,
> and verify its validation before use.
> 
> Fixes: 8b10d3653735 ("f2fs: introduce FAULT_NO_SEGMENT")
> Reported-by: syzbot+b6b347b7a4ea1b2e29b6@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/67973c2b.050a0220.11b1bb.0089.GAE@google.com
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
> v2:
> - get rid of potential blocking on curseg_mutex
>  fs/f2fs/inode.c   | 7 +++++++
>  fs/f2fs/segment.h | 9 ++++++++-
>  2 files changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index d6ad7810df69..6aec752ac098 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -793,6 +793,13 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
>  		!is_inode_flag_set(inode, FI_DIRTY_INODE))
>  		return 0;
>  
> +	/*
> +	 * no need to update inode page, ultimately f2fs_evict_inode() will
> +	 * clear dirty status of inode.
> +	 */
> +	if (f2fs_cp_error(sbi))
> +		return -EIO;
> +
>  	if (!f2fs_is_checkpoint_ready(sbi)) {
>  		f2fs_mark_inode_dirty_sync(inode, true);
>  		return -ENOSPC;
> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> index 943be4f1d6d2..0465dc00b349 100644
> --- a/fs/f2fs/segment.h
> +++ b/fs/f2fs/segment.h
> @@ -559,13 +559,16 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi,
>  			unsigned int node_blocks, unsigned int data_blocks,
>  			unsigned int dent_blocks)
>  {
> -
>  	unsigned int segno, left_blocks, blocks;
>  	int i;
>  
>  	/* check current data/node sections in the worst case. */
>  	for (i = CURSEG_HOT_DATA; i < NR_PERSISTENT_LOG; i++) {
>  		segno = CURSEG_I(sbi, i)->segno;
> +
> +		if (unlikely(segno == NULL_SEGNO))
> +			return false;
> +
>  		left_blocks = CAP_BLKS_PER_SEC(sbi) -
>  				get_ckpt_valid_blocks(sbi, segno, true);
>  
> @@ -576,6 +579,10 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi,
>  
>  	/* check current data section for dentry blocks. */
>  	segno = CURSEG_I(sbi, CURSEG_HOT_DATA)->segno;
> +
> +	if (unlikely(segno == NULL_SEGNO))
> +		return false;
> +
>  	left_blocks = CAP_BLKS_PER_SEC(sbi) -
>  			get_ckpt_valid_blocks(sbi, segno, true);
>  	if (dent_blocks > left_blocks)


  reply	other threads:[~2025-03-05  9:16 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-24 10:29 [f2fs-dev] [PATCH v2] f2fs: fix to avoid accessing uninitialized curseg Chao Yu via Linux-f2fs-devel
2025-02-24 10:29 ` Chao Yu
2025-03-05  9:16 ` Chao Yu via Linux-f2fs-devel [this message]
2025-03-05  9:16   ` Chao Yu
2025-03-11 19:50 ` [f2fs-dev] " patchwork-bot+f2fs--- via Linux-f2fs-devel
2025-03-11 19:50   ` patchwork-bot+f2fs

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9be24599-39de-4440-bd49-8f0629fa8a2b@kernel.org \
    --to=linux-f2fs-devel@lists.sourceforge.net \
    --cc=chao@kernel.org \
    --cc=jaegeuk@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=syzbot+b6b347b7a4ea1b2e29b6@syzkaller.appspotmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.