From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Lidong Chen Date: Fri, 22 Nov 2024 06:27:59 +0000 Subject: [PATCH] fs/jfs: Fix OOB read in jfs_getent() The JFS fuzzing revealed an OOB read in grub_jfs_getent(). The crash was caused by an invalid leaf nodes count, diro->dirpage->header.count, which was larger than the maximum number of leaf nodes allowed in an inode. This fix is to ensure that the leaf nodes count is validated in grub_jfs_opendir() before calling grub_jfs_getent(). On the occasion replace existing raw numbers with newly defined constant. Signed-off-by: Lidong Chen Reviewed-by: Daniel Kiper Reviewed-by: Alec Brown --- grub-core/fs/jfs.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 20d966abf..d4207eb64 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -41,6 +41,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_JFS_TREE_LEAF 2 +/* + * Define max entries stored in-line in an inode. + * https://jfs.sourceforge.net/project/pub/jfslayout.pdf + */ +#define GRUB_JFS_INODE_INLINE_ENTRIES 8 + struct grub_jfs_sblock { /* The magic for JFS. It should contain the string "JFS1". */ @@ -203,9 +209,9 @@ struct grub_jfs_inode grub_uint8_t freecnt; grub_uint8_t freelist; grub_uint32_t idotdot; - grub_uint8_t sorted[8]; + grub_uint8_t sorted[GRUB_JFS_INODE_INLINE_ENTRIES]; } header; - struct grub_jfs_leaf_dirent dirents[8]; + struct grub_jfs_leaf_dirent dirents[GRUB_JFS_INODE_INLINE_ENTRIES]; } GRUB_PACKED dir; /* Fast symlink. */ struct @@ -453,6 +459,13 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode) /* Check if the entire tree is contained within the inode. */ if (inode->file.tree.flags & GRUB_JFS_TREE_LEAF) { + if (inode->dir.header.count > GRUB_JFS_INODE_INLINE_ENTRIES) + { + grub_free (diro); + grub_error (GRUB_ERR_BAD_FS, N_("invalid JFS inode")); + return 0; + } + diro->leaf = inode->dir.dirents; diro->next_leaf = (struct grub_jfs_leaf_next_dirent *) de; diro->sorted = inode->dir.header.sorted;