I've sent out a v3 just now with fixes for these. Thanks, Andrew
On Tue, May 20, 2025 at 11:34 AM Daniel Kiper <daniel.ki...@oracle.com> wrote: > I think you should change the order of this patch and patch #3. > > On Mon, May 19, 2025 at 09:03:18PM -0500, Andrew Hamilton wrote: > > Correct several memory access violations and hangs found during fuzzing. > > The issues fixed here could occur if certain specific malformed NTFS > > file systems were presented to GRUB. Currently, GRUB does not allow NTFS > > file system access when lockdown mode is enforced, so these should be of > > minimal impact. > > > > The changes made in this commit generally correct issues where pointers > > into data buffers were being calculated using lengths read from the > > NTFS file system without sufficient bounds / sanity checking; attempting > > to iterate through a buffer using a length read from the NTFS file system > > without confirming the length is larger than 0 (possible hang / infinite > > loop); or attempting to access elements of a structure to free them, when > > the structure pointer is null. > > s/null/NULL/ > > Is it possible to group the changes logically and put them in > separate patches? The leftovers can be put into one last patch. > > > Signed-off-by: Andrew Hamilton <adham...@gmail.com> > > --- > > grub-core/fs/ntfs.c | 95 ++++++++++++++++++++++++++++++++++++++------- > > 1 file changed, 80 insertions(+), 15 deletions(-) > > > > diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c > > index 0d087acd8..45fff2400 100644 > > --- a/grub-core/fs/ntfs.c > > +++ b/grub-core/fs/ntfs.c > > @@ -246,6 +246,7 @@ fixup (grub_uint8_t *buf, grub_size_t len, const > grub_uint8_t *magic) > > grub_uint16_t ss; > > grub_uint8_t *pu; > > grub_uint16_t us; > > + grub_uint16_t pu_offset; > > > > COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == > GRUB_DISK_SECTOR_SIZE); > > > > @@ -255,7 +256,10 @@ fixup (grub_uint8_t *buf, grub_size_t len, const > grub_uint8_t *magic) > > ss = u16at (buf, 6) - 1; > > if (ss != len) > > return grub_error (GRUB_ERR_BAD_FS, "size not match"); > > - pu = buf + u16at (buf, 4); > > + pu_offset = u16at (buf, 4); > > + if (pu_offset >= (len * GRUB_DISK_SECTOR_SIZE - (2 * ss))) > > + return grub_error (GRUB_ERR_BAD_FS, "pu offset size incorrect"); > > + pu = buf + pu_offset; > > us = u16at (pu, 0); > > buf -= 2; > > while (ss > 0) > > @@ -373,6 +377,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t > attr) > > > > new_pos = &at->emft_buf[first_attr_off (at->emft_buf)]; > > end = &at->emft_buf[emft_buf_size]; > > + at->end = end; > > > > while (new_pos && *new_pos != 0xFF) > > { > > @@ -395,7 +400,8 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t > attr) > > } > > at->attr_cur = at->attr_nxt; > > mft_end = at->mft->buf + (at->mft->data->mft_size << > GRUB_NTFS_BLK_SHR); > > - while (at->attr_cur >= at->mft->buf && at->attr_cur < mft_end && > *at->attr_cur != 0xFF) > > + while (at->attr_cur >= at->mft->buf && at->attr_cur < (mft_end - 4) > > + && *at->attr_cur != 0xFF) > > { > > /* We can't use validate_attribute here because this logic > > * seems to be used for both parsing through attributes > > @@ -412,7 +418,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t > attr) > > > > if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST) > > at->attr_end = at->attr_cur; > > - if ((*at->attr_cur == attr) || (attr == 0)) > > + if ((*at->attr_cur == attr) || (attr == 0) || (nsize == 0)) > > return at->attr_cur; > > at->attr_cur = at->attr_nxt; > > } > > @@ -442,13 +448,23 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t > attr) > > return NULL; > > } > > at->attr_nxt = at->edat_buf; > > - at->attr_end = at->edat_buf + u32at (pa, 0x30); > > + grub_uint32_t edat_offset = u32at (pa, 0x30); > > + if (edat_offset >= n) { > > + grub_error (GRUB_ERR_BAD_FS, "edat offset is out of bounds"); > > + return NULL; > > + } > > + at->attr_end = at->edat_buf + edat_offset; > > pa_end = at->edat_buf + n; > > } > > else > > { > > at->attr_nxt = at->attr_end + res_attr_data_off (pa); > > - at->attr_end = at->attr_end + u32at (pa, 4); > > + grub_uint32_t edat_offset = u32at (pa, 4); > > + if ((at->attr_end + edat_offset) >= (at->end)) { > > + grub_error (GRUB_ERR_BAD_FS, "edat offset is out of bounds"); > > + return NULL; > > + } > > + at->attr_end = at->attr_end + edat_offset; > > pa_end = at->mft->buf + (at->mft->data->mft_size << > GRUB_NTFS_BLK_SHR); > > } > > at->flags |= GRUB_NTFS_AF_ALST; > > @@ -470,7 +486,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t > attr) > > at->attr_nxt = NULL; > > } > > > > - if (at->attr_nxt >= at->attr_end || at->attr_nxt == NULL) > > + if ((at->attr_nxt + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE) >= > at->attr_end || at->attr_nxt == NULL) > > return NULL; > > > > if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == > GRUB_NTFS_AT_DATA)) > > @@ -537,13 +553,16 @@ locate_attr (struct grub_ntfs_attr *at, struct > grub_ntfs_file *mft, > > return NULL; > > if ((at->flags & GRUB_NTFS_AF_ALST) == 0) > > { > > + /* Used to make sure we're not stuck in a loop. */ > > + grub_uint8_t *last_pa = NULL; > > Missing empty line... > > > while (1) > > { > > pa = find_attr (at, attr); > > - if (pa == NULL) > > + if (pa == NULL || pa == last_pa) > > break; > > if (at->flags & GRUB_NTFS_AF_ALST) > > return pa; > > + last_pa = pa; > > } > > grub_errno = GRUB_ERR_NONE; > > free_attr (at); > > @@ -639,6 +658,7 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t > *pa, grub_uint8_t *dest, > > grub_disk_read_hook_t read_hook, void *read_hook_data) > > { > > struct grub_ntfs_rlst cc, *ctx; > > + grub_uint8_t *end_ptr = (pa + len); > > > > if (len == 0) > > return 0; > > @@ -671,7 +691,13 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t > *pa, grub_uint8_t *dest, > > return 0; > > } > > > > - ctx->cur_run = pa + u16at (pa, 0x20); > > + grub_uint16_t run_offset = u16at (pa, 0x20); > > Please move variable definition to proper place... > > Daniel >
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel