Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP5:GA
grub2.24427
0031-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-fou...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0031-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch of Package grub2.24427
From a5fcc1d7a4febb5bc20dde161a4069b2a4baf017 Mon Sep 17 00:00:00 2001 From: Darren Kenny <darren.kenny@oracle.com> Date: Tue, 29 Mar 2022 15:52:46 +0000 Subject: [PATCH 31/33] fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing The fuzzer is generating btrfs file systems that have chunks with invalid combinations of stripes and substripes for the given RAID configurations. After examining the Linux kernel fs/btrfs/tree-checker.c code, it appears that sub-stripes should only be applied to RAID10, and in that case there should only ever be 2 of them. Similarly, RAID single should only have 1 stripe, and RAID1/1C3/1C4 should have 2. 3 or 4 stripes respectively, which is what redundancy corresponds. Some of the chunks ended up with a size of 0, which grub_malloc() still returned memory for and in turn generated ASAN errors later when accessed. While it would be possible to specifically limit the number of stripes, a more correct test was on the combination of the chunk item, and the number of stripes by the size of the chunk stripe structure in comparison to the size of the chunk itself. Signed-off-by: Darren Kenny <darren.kenny@oracle.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> --- grub-core/fs/btrfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 7891efffe2..743d61da63 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -701,6 +701,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, return grub_error (GRUB_ERR_BAD_FS, "couldn't find the chunk descriptor"); + if (!chsize) + { + grub_dprintf ("btrfs", "zero-size chunk\n"); + return grub_error (GRUB_ERR_BAD_FS, + "got an invalid zero-size chunk"); + } chunk = grub_malloc (chsize); if (!chunk) return grub_errno; @@ -753,6 +759,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size), nstripes, NULL); + + /* For single, there should be exactly 1 stripe. */ + if (grub_le_to_cpu16 (chunk->nstripes) != 1) + { + grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n", + grub_le_to_cpu16 (chunk->nstripes)); + return grub_error (GRUB_ERR_BAD_FS, + "invalid RAID_SINGLE: nstripes != 1 (%u)", + grub_le_to_cpu16 (chunk->nstripes)); + } if (stripe_length == 0) stripe_length = 512; stripen = grub_divmod64 (off, stripe_length, &stripe_offset); @@ -767,6 +783,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, stripe_offset = off; csize = grub_le_to_cpu64 (chunk->size) - off; redundancy = 2; + + /* + * Redundancy, and substripes only apply to RAID10, and there + * should be exactly 2 sub-stripes. + */ + if (grub_le_to_cpu16 (chunk->nstripes) != redundancy) + { + grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n", + redundancy, grub_le_to_cpu16 (chunk->nstripes)); + return grub_error (GRUB_ERR_BAD_FS, + "invalid RAID1: nstripes != %u (%u)", + redundancy, grub_le_to_cpu16 (chunk->nstripes)); + } break; } case GRUB_BTRFS_CHUNK_TYPE_RAID0: @@ -803,6 +832,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, stripe_offset = low + chunk_stripe_length * high; csize = chunk_stripe_length - low; + + /* + * Substripes only apply to RAID10, and there + * should be exactly 2 sub-stripes. + */ + if (grub_le_to_cpu16 (chunk->nsubstripes) != 2) + { + grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)", + grub_le_to_cpu16 (chunk->nsubstripes)); + return grub_error (GRUB_ERR_BAD_FS, + "invalid RAID10: nsubstripes != 2 (%u)", + grub_le_to_cpu16 (chunk->nsubstripes)); + } + break; } default: @@ -819,6 +862,18 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, for (j = 0; j < 2; j++) { + grub_size_t est_chunk_alloc = 0; + + if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe), + grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) || + grub_add (est_chunk_alloc, + sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) || + est_chunk_alloc > chunk->size) + { + err = GRUB_ERR_BAD_FS; + break; + } + for (i = 0; i < redundancy; i++) { struct grub_btrfs_chunk_stripe *stripe; -- 2.34.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor