]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
ZFS: Check bonustype in addition to dnode type
authorVladimir Serbinenko <phcoder@gmail.com>
Thu, 6 Jul 2023 15:16:00 +0000 (17:16 +0200)
committerVladimir Serbinenko <phcoder@gmail.com>
Mon, 18 Sep 2023 00:44:35 +0000 (02:44 +0200)
Some dnodes are shared with properties zap. This is used
e.g. for quotas. Then dnode type is 0xc4 and GRUB stumbles on
this. Check bonus type and if it's ok then ignore dnode type mismatch

Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
grub-core/fs/zfs/zfs.c

index 221c914cb9ed103bf30fd75e3d9891a567111a9d..b5453e0062700018958facc652af013dccf3ce3a 100644 (file)
@@ -3382,8 +3382,11 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
       if (!err)
        err = zap_lookup (&subvol->mdn, snapname, &headobj, data, 0);
       if (!err)
-       err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET,
+       err = dnode_get (&(data->mos), headobj, 0,
                         &subvol->mdn, data);
+      if (!err && subvol->mdn.dn.dn_type != DMU_OT_DSL_DATASET && subvol->mdn.dn.dn_bonustype != DMU_OT_DSL_DATASET)
+       return grub_error(GRUB_ERR_BAD_FS, "incorrect dataset dnode type");
+
       if (err)
        {
          grub_free (fsname);
@@ -4015,7 +4018,7 @@ fill_fs_info (struct grub_dirhook_info *info,
 
   info->dir = 1;
 
-  if (mdn.dn.dn_type == DMU_OT_DSL_DIR)
+  if (mdn.dn.dn_type == DMU_OT_DSL_DIR || mdn.dn.dn_bonustype == DMU_OT_DSL_DIR)
     {
       headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian);
 
@@ -4167,8 +4170,10 @@ iterate_zap_fs (const char *name, grub_uint64_t val,
       grub_errno = 0;
       return 0;
     }
-  if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
+  if (mdn.dn.dn_type != DMU_OT_DSL_DIR && mdn.dn.dn_bonustype != DMU_OT_DSL_DIR) {
+    grub_dprintf ("zfs", "type = 0x%x, val = 0x%llx\n", mdn.dn.dn_type, (long long)val);
     return 0;
+  }
 
   err = fill_fs_info (&info, &mdn, ctx->data);
   if (err)
@@ -4198,7 +4203,7 @@ iterate_zap_snap (const char *name, grub_uint64_t val,
       return 0;
     }
 
-  if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
+  if (mdn.dn.dn_type != DMU_OT_DSL_DATASET && mdn.dn.dn_bonustype != DMU_OT_DSL_DATASET)
     return 0;
 
   err = fill_fs_info (&info, &mdn, ctx->data);
@@ -4270,7 +4275,10 @@ grub_zfs_dir (grub_device_t device, const char *path,
 
       zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx);
 
-      err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data);
+      err = dnode_get (&(data->mos), headobj, 0, &dn, data);
+      if (!err && dn.dn.dn_type != DMU_OT_DSL_DATASET && dn.dn.dn_bonustype != DMU_OT_DSL_DATASET)
+       return grub_error(GRUB_ERR_BAD_FS, "incorrect dataset dnode type");
+
       if (err)
        {
          zfs_unmount (data);