File 0007-kern-file-Implement-filesystem-reference-counting.patch of Package grub2.37159

From bf4e2bc4049aa754c622b37e586fb3b8df2fade9 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 10:15:03 +0100
Subject: [PATCH 07/20] kern/file: Implement filesystem reference counting

The grub_file_open() and grub_file_close() should be the only places
that allow a reference to a filesystem to stay open. So, add grub_dl_t
to grub_fs_t and set this in the GRUB_MOD_INIT() for each filesystem to
avoid issues when filesystems forget to do it themselves or do not track
their own references, e.g. squash4.

The fs_label(), fs_uuid(), fs_mtime() and fs_read() should all ref and
unref in the same function but it is essentially redundant in GRUB
single threaded model.

Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/affs.c     | 1 +
 grub-core/fs/bfs.c      | 1 +
 grub-core/fs/btrfs.c    | 1 +
 grub-core/fs/cbfs.c     | 1 +
 grub-core/fs/cpio.c     | 1 +
 grub-core/fs/cpio_be.c  | 1 +
 grub-core/fs/ext2.c     | 1 +
 grub-core/fs/fat.c      | 1 +
 grub-core/fs/hfs.c      | 1 +
 grub-core/fs/hfsplus.c  | 1 +
 grub-core/fs/iso9660.c  | 1 +
 grub-core/fs/jfs.c      | 1 +
 grub-core/fs/minix.c    | 1 +
 grub-core/fs/newc.c     | 1 +
 grub-core/fs/nilfs2.c   | 1 +
 grub-core/fs/ntfs.c     | 1 +
 grub-core/fs/odc.c      | 1 +
 grub-core/fs/proc.c     | 1 +
 grub-core/fs/reiserfs.c | 1 +
 grub-core/fs/romfs.c    | 1 +
 grub-core/fs/sfs.c      | 1 +
 grub-core/fs/squash4.c  | 1 +
 grub-core/fs/tar.c      | 1 +
 grub-core/fs/udf.c      | 1 +
 grub-core/fs/ufs.c      | 1 +
 grub-core/fs/xfs.c      | 1 +
 grub-core/fs/zfs/zfs.c  | 1 +
 grub-core/kern/file.c   | 7 +++++++
 include/grub/fs.h       | 4 ++++
 29 files changed, 38 insertions(+)

diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
index 91073795f9..5dffab28cd 100644
--- a/grub-core/fs/affs.c
+++ b/grub-core/fs/affs.c
@@ -701,6 +701,7 @@ static struct grub_fs grub_affs_fs =
 
 GRUB_MOD_INIT(affs)
 {
+  grub_affs_fs.mod = mod;
   grub_fs_register (&grub_affs_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c
index d2b490bce7..6afdfc9875 100644
--- a/grub-core/fs/bfs.c
+++ b/grub-core/fs/bfs.c
@@ -1104,6 +1104,7 @@ GRUB_MOD_INIT (bfs)
 {
   COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE ==
 		       sizeof (struct grub_bfs_extent));
+  grub_bfs_fs.mod = mod;
   grub_fs_register (&grub_bfs_fs);
 }
 
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 386819ad39..a8ae68fd71 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -3032,6 +3032,7 @@ relpath_set_env (struct grub_env_var *var,
 
 GRUB_MOD_INIT (btrfs)
 {
+  grub_btrfs_fs.mod = mod;
   grub_fs_register (&grub_btrfs_fs);
   cmd_info = grub_register_command("btrfs-info", grub_cmd_btrfs_info,
 				   "DEVICE",
diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
index 0842701a60..395edcbbdf 100644
--- a/grub-core/fs/cbfs.c
+++ b/grub-core/fs/cbfs.c
@@ -390,6 +390,7 @@ GRUB_MOD_INIT (cbfs)
 #if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
   init_cbfsdisk ();
 #endif
+  grub_cbfs_fs.mod = mod;
   grub_fs_register (&grub_cbfs_fs);
 }
 
diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c
index dab5f98988..1799f7ff5a 100644
--- a/grub-core/fs/cpio.c
+++ b/grub-core/fs/cpio.c
@@ -52,6 +52,7 @@ read_number (const grub_uint16_t *arr, grub_size_t size)
 
 GRUB_MOD_INIT (cpio)
 {
+  grub_cpio_fs.mod = mod;
   grub_fs_register (&grub_cpio_fs);
 }
 
diff --git a/grub-core/fs/cpio_be.c b/grub-core/fs/cpio_be.c
index 8465488921..7bed1b848c 100644
--- a/grub-core/fs/cpio_be.c
+++ b/grub-core/fs/cpio_be.c
@@ -52,6 +52,7 @@ read_number (const grub_uint16_t *arr, grub_size_t size)
 
 GRUB_MOD_INIT (cpio_be)
 {
+  grub_cpio_fs.mod = mod;
   grub_fs_register (&grub_cpio_fs);
 }
 
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
index ecb69ed402..55d73394a9 100644
--- a/grub-core/fs/ext2.c
+++ b/grub-core/fs/ext2.c
@@ -1075,6 +1075,7 @@ static struct grub_fs grub_ext2_fs =
 
 GRUB_MOD_INIT(ext2)
 {
+  grub_ext2_fs.mod = mod;
   grub_fs_register (&grub_ext2_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c
index 8d8dc35ce0..72785a7981 100644
--- a/grub-core/fs/fat.c
+++ b/grub-core/fs/fat.c
@@ -1254,6 +1254,7 @@ GRUB_MOD_INIT(fat)
 #endif
 {
   COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
+  grub_fat_fs.mod = mod;
   grub_fs_register (&grub_fat_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
index a79c83321e..1f0b9b5035 100644
--- a/grub-core/fs/hfs.c
+++ b/grub-core/fs/hfs.c
@@ -1433,6 +1433,7 @@ static struct grub_fs grub_hfs_fs =
 
 GRUB_MOD_INIT(hfs)
 {
+  grub_hfs_fs.mod = mod;
   grub_fs_register (&grub_hfs_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
index 4cbfe71b55..dc6c13a064 100644
--- a/grub-core/fs/hfsplus.c
+++ b/grub-core/fs/hfsplus.c
@@ -1117,6 +1117,7 @@ static struct grub_fs grub_hfsplus_fs =
 
 GRUB_MOD_INIT(hfsplus)
 {
+  grub_hfsplus_fs.mod = mod;
   grub_fs_register (&grub_hfsplus_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
index 6fc9302bce..1f85dc5c8c 100644
--- a/grub-core/fs/iso9660.c
+++ b/grub-core/fs/iso9660.c
@@ -1152,6 +1152,7 @@ static struct grub_fs grub_iso9660_fs =
 
 GRUB_MOD_INIT(iso9660)
 {
+  grub_iso9660_fs.mod = mod;
   grub_fs_register (&grub_iso9660_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index 8b29a97cfc..5c578be6d0 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -952,6 +952,7 @@ static struct grub_fs grub_jfs_fs =
 
 GRUB_MOD_INIT(jfs)
 {
+  grub_jfs_fs.mod = mod;
   grub_fs_register (&grub_jfs_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c
index d451b34266..28571c49e6 100644
--- a/grub-core/fs/minix.c
+++ b/grub-core/fs/minix.c
@@ -716,6 +716,7 @@ GRUB_MOD_INIT(minix)
 #endif
 #endif
 {
+  grub_minix_fs.mod = mod;
   grub_fs_register (&grub_minix_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/newc.c b/grub-core/fs/newc.c
index 4fb8b2e3d2..43b7f8b642 100644
--- a/grub-core/fs/newc.c
+++ b/grub-core/fs/newc.c
@@ -64,6 +64,7 @@ read_number (const char *str, grub_size_t size)
 
 GRUB_MOD_INIT (newc)
 {
+  grub_cpio_fs.mod = mod;
   grub_fs_register (&grub_cpio_fs);
 }
 
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
index 598a2a55ba..14597efc08 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -1213,6 +1213,7 @@ GRUB_MOD_INIT (nilfs2)
 				  grub_nilfs2_dat_entry));
   COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
 		       == sizeof (struct grub_nilfs2_inode));
+  grub_nilfs2_fs.mod = mod;
   grub_fs_register (&grub_nilfs2_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index d3fb5b48f5..4e1d234441 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -1316,6 +1316,7 @@ static struct grub_fs grub_ntfs_fs =
 
 GRUB_MOD_INIT (ntfs)
 {
+  grub_ntfs_fs.mod = mod;
   grub_fs_register (&grub_ntfs_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/odc.c b/grub-core/fs/odc.c
index 790000622d..8e4e8aeac8 100644
--- a/grub-core/fs/odc.c
+++ b/grub-core/fs/odc.c
@@ -52,6 +52,7 @@ read_number (const char *str, grub_size_t size)
 
 GRUB_MOD_INIT (odc)
 {
+  grub_cpio_fs.mod = mod;
   grub_fs_register (&grub_cpio_fs);
 }
 
diff --git a/grub-core/fs/proc.c b/grub-core/fs/proc.c
index 31f3aa9a4c..317118b815 100644
--- a/grub-core/fs/proc.c
+++ b/grub-core/fs/proc.c
@@ -192,6 +192,7 @@ static struct grub_fs grub_procfs_fs =
 
 GRUB_MOD_INIT (procfs)
 {
+  grub_procfs_fs.mod = mod;
   grub_disk_dev_register (&grub_procfs_dev);
   grub_fs_register (&grub_procfs_fs);
 }
diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
index 39736f63c6..420497b223 100644
--- a/grub-core/fs/reiserfs.c
+++ b/grub-core/fs/reiserfs.c
@@ -1417,6 +1417,7 @@ static struct grub_fs grub_reiserfs_fs =
 
 GRUB_MOD_INIT(reiserfs)
 {
+  grub_reiserfs_fs.mod = mod;
   grub_fs_register (&grub_reiserfs_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c
index 2e35444085..f282cff860 100644
--- a/grub-core/fs/romfs.c
+++ b/grub-core/fs/romfs.c
@@ -475,6 +475,7 @@ static struct grub_fs grub_romfs_fs =
 
 GRUB_MOD_INIT(romfs)
 {
+  grub_romfs_fs.mod = mod;
   grub_fs_register (&grub_romfs_fs);
 }
 
diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
index 3ddc6b5e28..223b6785c2 100644
--- a/grub-core/fs/sfs.c
+++ b/grub-core/fs/sfs.c
@@ -772,6 +772,7 @@ static struct grub_fs grub_sfs_fs =
 
 GRUB_MOD_INIT(sfs)
 {
+  grub_sfs_fs.mod = mod;
   grub_fs_register (&grub_sfs_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
index f9bef38fc4..1505832d54 100644
--- a/grub-core/fs/squash4.c
+++ b/grub-core/fs/squash4.c
@@ -1032,6 +1032,7 @@ static struct grub_fs grub_squash_fs =
 
 GRUB_MOD_INIT(squash4)
 {
+  grub_squash_fs.mod = mod;
   grub_fs_register (&grub_squash_fs);
 }
 
diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
index a361808738..255c1d1a31 100644
--- a/grub-core/fs/tar.c
+++ b/grub-core/fs/tar.c
@@ -349,6 +349,7 @@ static struct grub_fs grub_cpio_fs = {
 
 GRUB_MOD_INIT (tar)
 {
+  grub_cpio_fs.mod = mod;
   grub_fs_register (&grub_cpio_fs);
 }
 
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
index 99b001f206..1e821e4b92 100644
--- a/grub-core/fs/udf.c
+++ b/grub-core/fs/udf.c
@@ -1235,6 +1235,7 @@ static struct grub_fs grub_udf_fs = {
 
 GRUB_MOD_INIT (udf)
 {
+  grub_udf_fs.mod = mod;
   grub_fs_register (&grub_udf_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
index 0c2004fd76..a2c63d6461 100644
--- a/grub-core/fs/ufs.c
+++ b/grub-core/fs/ufs.c
@@ -899,6 +899,7 @@ GRUB_MOD_INIT(ufs1)
 #endif
 #endif
 {
+  grub_ufs_fs.mod = mod;
   grub_fs_register (&grub_ufs_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index a600f9edc6..29efc89f71 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -1189,6 +1189,7 @@ static struct grub_fs grub_xfs_fs =
 
 GRUB_MOD_INIT(xfs)
 {
+  grub_xfs_fs.mod = mod;
   grub_fs_register (&grub_xfs_fs);
   my_mod = mod;
 }
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index c6204367e7..3299cc9b30 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -4374,6 +4374,7 @@ static struct grub_fs grub_zfs_fs = {
 GRUB_MOD_INIT (zfs)
 {
   COMPILE_TIME_ASSERT (sizeof (zap_leaf_chunk_t) == ZAP_LEAF_CHUNKSIZE);
+  grub_zfs_fs.mod = mod;
   grub_fs_register (&grub_zfs_fs);
 #ifndef GRUB_UTIL
   my_mod = mod;
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
index 1a325c478d..66543ac80b 100644
--- a/grub-core/kern/file.c
+++ b/grub-core/kern/file.c
@@ -25,6 +25,7 @@
 #include <grub/fs.h>
 #include <grub/device.h>
 #include <grub/i18n.h>
+#include <grub/dl.h>
 
 void (*EXPORT_VAR (grub_grubnet_fini)) (void);
 
@@ -115,6 +116,9 @@ grub_file_open (const char *name)
   if (file->data == NULL)
     goto fail;
 
+  if (file->fs->mod)
+    grub_dl_ref (file->fs->mod);
+
   file->name = grub_strdup (name);
   grub_errno = GRUB_ERR_NONE;
 
@@ -196,6 +200,9 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len)
 grub_err_t
 grub_file_close (grub_file_t file)
 {
+  if (file->fs->mod)
+    grub_dl_unref (file->fs->mod);
+
   if (file->fs->close)
     (file->fs->close) (file);
 
diff --git a/include/grub/fs.h b/include/grub/fs.h
index 5678c60c2d..cb1040b50c 100644
--- a/include/grub/fs.h
+++ b/include/grub/fs.h
@@ -23,6 +23,7 @@
 #include <grub/device.h>
 #include <grub/symbol.h>
 #include <grub/types.h>
+#include <grub/dl.h>
 
 #include <grub/list.h>
 /* For embedding types.  */
@@ -57,6 +58,9 @@ struct grub_fs
   /* My name.  */
   const char *name;
 
+  /* My module */
+  grub_dl_t mod;
+
   /* Call HOOK with each file under DIR.  */
   grub_err_t (*dir) (grub_device_t device, const char *path,
 		     grub_fs_dir_hook_t hook, void *hook_data);
-- 
2.48.1

openSUSE Build Service is sponsored by