Re: [PATCH] udf: Mark LVID buffer as uptodate before marking it dirty

Jan Kara <[email protected]>
Newsgroups dev.linux.lists.syzbot,org.kernel.vger.linux-kernel
Message-ID <m3sbeyqcoykao3mvz2e33jxixcohrawowcqcagfcf444qxkbve@rddlcubo7wze>
On Tue 23-06-26 12:30:52, syzbot wrote:
> From: Aleksandr Nogikh <[email protected]>
> 
> When an I/O error occurs while writing the Logical Volume Integrity
> Descriptor (LVID) buffer to the block device, the block layer's completion
> handler (`end_buffer_write_sync()`) clears the `BH_Uptodate` flag on the
> buffer. However, the buffer still contains valid LVID data in memory. If
> the filesystem is subsequently remounted read-write or synced,
> `udf_open_lvid()` or `udf_sync_fs()` will modify the LVID buffer and call
> `mark_buffer_dirty()`. This triggers a spurious
> `WARN_ON_ONCE(!buffer_uptodate(bh))` warning in `mark_buffer_dirty()`
> because the buffer is not marked uptodate, even though its in-memory
> contents are valid and are about to be overwritten.
> 
> To prevent this spurious warning, unconditionally set the `BH_Uptodate`
> flag before calling `mark_buffer_dirty()` in `udf_open_lvid()` and
> `udf_sync_fs()`. This acknowledges that the in-memory buffer is valid and
> matches the workaround previously applied to `udf_close_lvid()` in commit
> 853a0c25baf9 ("udf: Mark LVID buffer as uptodate before marking it dirty").
> Extending this workaround ensures consistent behavior across all LVID
> updates.
> 
> Buffer I/O error on dev loop0, logical block 128, lost sync page write
> ------------[ cut here ]------------
> !buffer_uptodate(bh)
> WARNING: fs/buffer.c:1087 at mark_buffer_dirty+0x299/0x410 fs/buffer.c:1087
> ...
> Call Trace:
>  <TASK>
>  udf_open_lvid+0x369/0x5b0 fs/udf/super.c:2078
>  udf_reconfigure+0x336/0x540 fs/udf/super.c:679
>  reconfigure_super+0x232/0x8f0 fs/super.c:1080
>  vfs_cmd_reconfigure fs/fsopen.c:268 [inline]
>  vfs_fsconfig_locked+0x171/0x320 fs/fsopen.c:297
>  __do_sys_fsconfig fs/fsopen.c:463 [inline]
>  __se_sys_fsconfig+0x6b9/0x810 fs/fsopen.c:350
>  do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
>  </TASK>
> 
> Fixes: 853a0c25baf9 ("udf: Mark LVID buffer as uptodate before marking it dirty")
> Assisted-by: Gemini:gemini-3.1-pro-preview Gemini:gemini-3-flash-preview syzbot
> Reported-by: [email protected]
> Closes: https://syzkaller.appspot.com/bug?extid=0306b38d9ed6ef71467d
> Link: https://syzkaller.appspot.com/ai_job?id=05f8e20f-f080-4c7f-a206-08dbc15cb4a1
> Signed-off-by: Aleksandr Nogikh <[email protected]>

Thanks. I've added the patch to my tree.

								Honza

> 
> ---
> diff --git a/fs/udf/super.c b/fs/udf/super.c
> index cad2e15d6..7fa2e52cf 100644
> --- a/fs/udf/super.c
> +++ b/fs/udf/super.c
> @@ -2040,6 +2040,17 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
>  	return 0;
>  }
>  
> +static void udf_mark_buffer_dirty(struct buffer_head *bh)
> +{
> +	/*
> +	 * We set buffer uptodate unconditionally here to avoid spurious
> +	 * warnings from mark_buffer_dirty() when previous EIO has marked
> +	 * the buffer as !uptodate
> +	 */
> +	set_buffer_uptodate(bh);
> +	mark_buffer_dirty(bh);
> +}
> +
>  static void udf_finalize_lvid(struct logicalVolIntegrityDesc *lvid)
>  {
>  	struct timespec64 ts;
> @@ -2075,7 +2086,7 @@ static void udf_open_lvid(struct super_block *sb)
>  		UDF_SET_FLAG(sb, UDF_FLAG_INCONSISTENT);
>  
>  	udf_finalize_lvid(lvid);
> -	mark_buffer_dirty(bh);
> +	udf_mark_buffer_dirty(bh);
>  	sbi->s_lvid_dirty = 0;
>  	mutex_unlock(&sbi->s_alloc_mutex);
>  	/* Make opening of filesystem visible on the media immediately */
> @@ -2108,14 +2119,8 @@ static void udf_close_lvid(struct super_block *sb)
>  	if (!UDF_QUERY_FLAG(sb, UDF_FLAG_INCONSISTENT))
>  		lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
>  
> -	/*
> -	 * We set buffer uptodate unconditionally here to avoid spurious
> -	 * warnings from mark_buffer_dirty() when previous EIO has marked
> -	 * the buffer as !uptodate
> -	 */
> -	set_buffer_uptodate(bh);
>  	udf_finalize_lvid(lvid);
> -	mark_buffer_dirty(bh);
> +	udf_mark_buffer_dirty(bh);
>  	sbi->s_lvid_dirty = 0;
>  	mutex_unlock(&sbi->s_alloc_mutex);
>  	/* Make closing of filesystem visible on the media immediately */
> @@ -2397,7 +2402,7 @@ static int udf_sync_fs(struct super_block *sb, int wait)
>  		 * Blockdevice will be synced later so we don't have to submit
>  		 * the buffer for IO
>  		 */
> -		mark_buffer_dirty(bh);
> +		udf_mark_buffer_dirty(bh);
>  		sbi->s_lvid_dirty = 0;
>  	}
>  	mutex_unlock(&sbi->s_alloc_mutex);
> 
> 
> base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
> -- 
> See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
> You can comment on the patch as usual, syzbot will try to address
> the comments and send a new version of the patch if necessary.
> syzbot engineers can be reached at [email protected].
-- 
Jan Kara <[email protected]>
SUSE Labs, CR
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.