grub2/debian/patches/cve_2025_02_multiple/0156-kern-file-Implement-filesystem-reference-counting.patch
Fabian Grünbichler a7a440dc54 revert broken NTFS patches
NTFS is disabled with secure boot enabled anyway now, and these patches
caused a regression both for grub during boot and grub_mount in
userspace.

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
2025-03-20 11:52:33 +01:00

446 lines
12 KiB
Diff

From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 10:15:03 +0100
Subject: kern/file: Implement filesystem reference counting
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
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>
(cherry picked from commit 16f196874fbe360a1b3c66064ec15adadf94c57b)
FG: remove hunk for EROFS, not part of 2.06 yet
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.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/f2fs.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 ++++
30 files changed, 39 insertions(+)
diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
index cafcd0f..b1c64e7 100644
--- a/grub-core/fs/affs.c
+++ b/grub-core/fs/affs.c
@@ -699,6 +699,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 47dbe20..1770581 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 54a46b8..bb608f5 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -2312,6 +2312,7 @@ static struct grub_fs grub_btrfs_fs = {
GRUB_MOD_INIT (btrfs)
{
+ grub_btrfs_fs.mod = mod;
grub_fs_register (&grub_btrfs_fs);
}
diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
index 8ab7106..2332745 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 dab5f98..1799f7f 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 8465488..7bed1b8 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 a253018..4925d1d 100644
--- a/grub-core/fs/ext2.c
+++ b/grub-core/fs/ext2.c
@@ -1119,6 +1119,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/f2fs.c b/grub-core/fs/f2fs.c
index db8a65f..f6d6bea 100644
--- a/grub-core/fs/f2fs.c
+++ b/grub-core/fs/f2fs.c
@@ -1353,6 +1353,7 @@ static struct grub_fs grub_f2fs_fs = {
GRUB_MOD_INIT (f2fs)
{
+ grub_f2fs_fs.mod = mod;
grub_fs_register (&grub_f2fs_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c
index dd82e4e..26f36d2 100644
--- a/grub-core/fs/fat.c
+++ b/grub-core/fs/fat.c
@@ -1315,6 +1315,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 bb7af5f..3a98944 100644
--- a/grub-core/fs/hfs.c
+++ b/grub-core/fs/hfs.c
@@ -1434,6 +1434,7 @@ static struct grub_fs grub_hfs_fs =
GRUB_MOD_INIT(hfs)
{
+ grub_hfs_fs.mod = mod;
if (!grub_is_lockdown ())
grub_fs_register (&grub_hfs_fs);
my_mod = mod;
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
index e7fd98a..d5f9000 100644
--- a/grub-core/fs/hfsplus.c
+++ b/grub-core/fs/hfsplus.c
@@ -1150,6 +1150,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 7a59a65..0c0aae5 100644
--- a/grub-core/fs/iso9660.c
+++ b/grub-core/fs/iso9660.c
@@ -1165,6 +1165,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 70a2f49..b0283ac 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -1005,6 +1005,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 3cd18c8..beb1a63 100644
--- a/grub-core/fs/minix.c
+++ b/grub-core/fs/minix.c
@@ -732,6 +732,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 4fb8b2e..43b7f8b 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 3c248a9..c44583e 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -1231,6 +1231,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 deb058a..0ffcc9c 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 7900006..8e4e8ae 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 5f51650..bcde433 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 af6a226..86ea99d 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 d97b8fb..a43546d 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 983e880..f0d7cac 100644
--- a/grub-core/fs/sfs.c
+++ b/grub-core/fs/sfs.c
@@ -779,6 +779,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 6dd731e..ccfa3ee 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 386c090..fd2ec1f 100644
--- a/grub-core/fs/tar.c
+++ b/grub-core/fs/tar.c
@@ -354,6 +354,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 2ac5c1d..3d4b402 100644
--- a/grub-core/fs/udf.c
+++ b/grub-core/fs/udf.c
@@ -1382,6 +1382,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 4727266..7f72494 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 296ab55..3317dd3 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -1277,6 +1277,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 cf4d2ab..cbbd867 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -4394,6 +4394,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 a06ff3b..f123ec5 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);
@@ -117,6 +118,9 @@ grub_file_open (const char *name, enum grub_file_type type)
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;
@@ -197,6 +201,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->fs_close)
(file->fs->fs_close) (file);
diff --git a/include/grub/fs.h b/include/grub/fs.h
index 026bc3b..df4c93b 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 (*fs_dir) (grub_device_t device, const char *path,
grub_fs_dir_hook_t hook, void *hook_data);