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