Re: [PATCH 1/2] ufs: create the root dentry after loading cylinder metadata

Jan Kara <[email protected]> Mon, 3 Aug 2026 12:06:38 +0200
Newsgroups org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <q6zgjx7g3ciaxfbc6wnmgafuc6bsyz53opvljuogfblwxy45hb@nkpbchrwbngx>
On Sat 01-08-26 10:12:57, Ali Ahmet Memis wrote:
> ufs_fill_super() installed sb->s_root before it loaded the cylinder
> group structures for a writable mount:
> 
> 	sb->s_root = d_make_root(inode);
> 	...
> 	if (!sb_rdonly(sb))
> 		if (!ufs_read_cylinder_structures(sb))
> 			goto failed;
> 
> When ufs_read_cylinder_structures() failed, the error path freed the
> in-core superblock information and set sb->s_fs_info to NULL while
> sb->s_root stayed installed. get_tree_bdev() then reached
> deactivate_locked_super(), and because s_root was present,
> generic_shutdown_super() called sync_filesystem() and the put_super
> operation. Both dereference UFS_SB(sb), which is now NULL, so a mount
> that fails only while reading the cylinder groups oopses during
> teardown. A crafted image whose first cylinder group cannot be read
> reaches this path.
> 
> Load the cylinder group metadata first and create the root dentry last,
> so the superblock is published to the VFS only once it is fully set up.
> ufs_setup_cstotal() and ufs_read_cylinder_structures() take only the
> super_block and do not use the root inode, so the reordering is safe.
> 
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: [email protected]
> Signed-off-by: Ali Ahmet Memis <[email protected]>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <[email protected]>

								Honza

> ---
>  fs/ufs/super.c | 17 +++++++++--------
>  1 file changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/fs/ufs/super.c b/fs/ufs/super.c
> index c4831a8b9..7deecb395 100644
> --- a/fs/ufs/super.c
> +++ b/fs/ufs/super.c
> @@ -1199,6 +1199,15 @@ static int ufs_fill_super(struct super_block *sb, struct fs_context *fc)
>  	sb->s_maxbytes = ufs_max_bytes(sb);
>  	sb->s_max_links = UFS_LINK_MAX;
>  
> +	ufs_setup_cstotal(sb);
> +	/*
> +	 * Read cylinder group structures
> +	 */
> +	if (!sb_rdonly(sb))
> +		if (!ufs_read_cylinder_structures(sb))
> +			goto failed;
> +
> +	/* create the root dentry last, once UFS_SB(sb) is fully set up */
>  	inode = ufs_iget(sb, UFS_ROOTINO);
>  	if (IS_ERR(inode)) {
>  		ret = PTR_ERR(inode);
> @@ -1210,14 +1219,6 @@ static int ufs_fill_super(struct super_block *sb, struct fs_context *fc)
>  		goto failed;
>  	}
>  
> -	ufs_setup_cstotal(sb);
> -	/*
> -	 * Read cylinder group structures
> -	 */
> -	if (!sb_rdonly(sb))
> -		if (!ufs_read_cylinder_structures(sb))
> -			goto failed;
> -
>  	UFSD("EXIT\n");
>  	return 0;
>  
> -- 
> 2.54.0
> 
-- 
Jan Kara <[email protected]>
SUSE Labs, CR