From 1333b34a3ef0cd5c74447e8b7a447b464030566e Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phco...@gmail.com>
Date: Thu, 6 Jul 2023 17:16:00 +0200
Subject: [PATCH 4/4] ZFS: Check bonustype in addition to dnode type

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 <phco...@gmail.com>
---
 grub-core/fs/zfs/zfs.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index 221c914cb..b5453e006 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -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);
-- 
2.39.2

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to