- Resolves: CVE-2024-45779 CVE-2024-45778 CVE-2025-1118 - Resolves: CVE-2025-0677 CVE-2024-45782 CVE-2025-0690 - Resolves: CVE-2024-45783 CVE-2025-0624 CVE-2024-45776 - Resolves: CVE-2025-0622 CVE-2024-45774 CVE-2024-45775 - Resolves: CVE-2024-45781 CVE-2024-45780 - Resolves: #RHEL-79700 - Resolves: #RHEL-79341 - Resolves: #RHEL-79875 - Resolves: #RHEL-79849 - Resolves: #RHEL-79707 - Resolves: #RHEL-79857 - Resolves: #RHEL-79709 - Resolves: #RHEL-79846 - Resolves: #RHEL-75737 - Resolves: #RHEL-79713 - Resolves: #RHEL-73785 - Resolves: #RHEL-73787 - Resolves: #RHEL-79704 - Resolves: #RHEL-79702 Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
129 lines
5.2 KiB
Diff
129 lines
5.2 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
From: Lidong Chen <lidong.chen@oracle.com>
|
||
Date: Mon, 16 Dec 2024 20:22:39 +0000
|
||
Subject: [PATCH] fs/jfs: Use full 40 bits offset and address for a data extent
|
||
|
||
An extent's logical offset and address are represented as a 40-bit value
|
||
split into two parts: the most significant 8 bits and the least
|
||
significant 32 bits. Currently the JFS code uses only the least
|
||
significant 32 bits value for offsets and addresses assuming the data
|
||
size will never exceed the 32-bit range. This approach ignores the most
|
||
significant 8 bits potentially leading to incorrect offsets and
|
||
addresses for larger values. The patch fixes it by incorporating the
|
||
most significant 8 bits into the calculation to get the full 40-bits
|
||
value for offsets and addresses.
|
||
|
||
https://jfs.sourceforge.net/project/pub/jfslayout.pdf
|
||
|
||
"off1,off2 is a 40-bit field, containing the logical offset of the first
|
||
block in the extent.
|
||
...
|
||
addr1,addr2 is a 40-bit field, containing the address of the extent."
|
||
|
||
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
|
||
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
|
||
Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
|
||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||
---
|
||
grub-core/fs/jfs.c | 41 +++++++++++++++++++++++++++++------------
|
||
1 file changed, 29 insertions(+), 12 deletions(-)
|
||
|
||
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
|
||
index 88fb884df..2bde48d45 100644
|
||
--- a/grub-core/fs/jfs.c
|
||
+++ b/grub-core/fs/jfs.c
|
||
@@ -265,6 +265,20 @@ static grub_dl_t my_mod;
|
||
|
||
static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino);
|
||
|
||
+/*
|
||
+ * An extent's offset, physical and logical, is represented as a 40-bit value.
|
||
+ * This 40-bit value is split into two parts:
|
||
+ * - offset1: the most signficant 8 bits of the offset,
|
||
+ * - offset2: the least significant 32 bits of the offset.
|
||
+ *
|
||
+ * This function calculates and returns the 64-bit offset of an extent.
|
||
+ */
|
||
+static grub_uint64_t
|
||
+get_ext_offset (grub_uint8_t offset1, grub_uint32_t offset2)
|
||
+{
|
||
+ return (((grub_uint64_t) offset1 << 32) | grub_le_to_cpu32 (offset2));
|
||
+}
|
||
+
|
||
static grub_int64_t
|
||
getblk (struct grub_jfs_treehead *treehead,
|
||
struct grub_jfs_tree_extent *extents,
|
||
@@ -274,22 +288,25 @@ getblk (struct grub_jfs_treehead *treehead,
|
||
{
|
||
int found = -1;
|
||
int i;
|
||
+ grub_uint64_t ext_offset, ext_blk;
|
||
|
||
for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 &&
|
||
i < max_extents; i++)
|
||
{
|
||
+ ext_offset = get_ext_offset (extents[i].offset1, extents[i].offset2);
|
||
+ ext_blk = get_ext_offset (extents[i].extent.blk1, extents[i].extent.blk2);
|
||
+
|
||
if (treehead->flags & GRUB_JFS_TREE_LEAF)
|
||
{
|
||
/* Read the leafnode. */
|
||
- if (grub_le_to_cpu32 (extents[i].offset2) <= blk
|
||
+ if (ext_offset <= blk
|
||
&& ((grub_le_to_cpu16 (extents[i].extent.length))
|
||
+ (extents[i].extent.length2 << 16)
|
||
- + grub_le_to_cpu32 (extents[i].offset2)) > blk)
|
||
- return (blk - grub_le_to_cpu32 (extents[i].offset2)
|
||
- + grub_le_to_cpu32 (extents[i].extent.blk2));
|
||
+ + ext_offset) > blk)
|
||
+ return (blk - ext_offset + ext_blk);
|
||
}
|
||
else
|
||
- if (blk >= grub_le_to_cpu32 (extents[i].offset2))
|
||
+ if (blk >= ext_offset)
|
||
found = i;
|
||
}
|
||
|
||
@@ -307,10 +324,9 @@ getblk (struct grub_jfs_treehead *treehead,
|
||
return -1;
|
||
|
||
if (!grub_disk_read (data->disk,
|
||
- ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2))
|
||
- << (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
||
- - GRUB_DISK_SECTOR_BITS), 0,
|
||
- sizeof (*tree), (char *) tree))
|
||
+ (grub_disk_addr_t) ext_blk
|
||
+ << (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS),
|
||
+ 0, sizeof (*tree), (char *) tree))
|
||
{
|
||
if (grub_memcmp (&tree->treehead, treehead, sizeof (struct grub_jfs_treehead)) ||
|
||
grub_memcmp (&tree->extents, extents, 254 * sizeof (struct grub_jfs_tree_extent)))
|
||
@@ -361,7 +377,7 @@ grub_jfs_read_inode (struct grub_jfs_data *data, grub_uint32_t ino,
|
||
sizeof (iag_inodes), &iag_inodes))
|
||
return grub_errno;
|
||
|
||
- inoblk = grub_le_to_cpu32 (iag_inodes[inoext].blk2);
|
||
+ inoblk = get_ext_offset (iag_inodes[inoext].blk1, iag_inodes[inoext].blk2);
|
||
inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
||
- GRUB_DISK_SECTOR_BITS);
|
||
inoblk += inonum;
|
||
@@ -490,7 +506,8 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
|
||
return 0;
|
||
}
|
||
|
||
- blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2);
|
||
+ blk = get_ext_offset (de[inode->dir.header.sorted[0]].ex.blk1,
|
||
+ de[inode->dir.header.sorted[0]].ex.blk2);
|
||
blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
|
||
|
||
/* Read in the nodes until we are on the leaf node level. */
|
||
@@ -508,7 +525,7 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
|
||
|
||
de = (struct grub_jfs_internal_dirent *) diro->dirpage->dirent;
|
||
index = diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
|
||
- blk = (grub_le_to_cpu32 (de[index].ex.blk2)
|
||
+ blk = (get_ext_offset (de[index].ex.blk1, de[index].ex.blk2)
|
||
<< (grub_le_to_cpu16 (data->sblock.log2_blksz)
|
||
- GRUB_DISK_SECTOR_BITS));
|
||
} while (!(diro->dirpage->header.flags & GRUB_JFS_TREE_LEAF));
|