From: Tulio A M Mendes Date: Tue, 26 May 2026 04:57:27 +0000 (-0300) Subject: security: fix ext2 superblock/GDT validation (C6) X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=db829e915e6f805d56840d092cd420e3cd8d1e7a;p=AdrOS.git security: fix ext2 superblock/GDT validation (C6) --- diff --git a/src/kernel/ext2.c b/src/kernel/ext2.c index 371ff64d..ca2dd10d 100644 --- a/src/kernel/ext2.c +++ b/src/kernel/ext2.c @@ -1460,9 +1460,23 @@ vfs_mount_result_t ext2_mount(block_device_t* bdev, uint32_t partition_lba) { return result; } + /* Validate s_blocks_per_group and s_inodes_per_group are non-zero */ + if (sb.s_blocks_per_group == 0) { + kprintf("[EXT2] Invalid s_blocks_per_group: 0\n"); + kfree(em); + return result; + } + if (sb.s_inodes_per_group == 0) { + kprintf("[EXT2] Invalid s_inodes_per_group: 0\n"); + kfree(em); + return result; + } + em->block_size = 1024U << sb.s_log_block_size; - if (em->block_size > 4096) { - kprintf("[EXT2] Unsupported block size %u\n", em->block_size); + /* Validate block_size is power of 2 and >= 1024 */ + if (em->block_size < 1024 || em->block_size > 4096 || + (em->block_size & (em->block_size - 1)) != 0) { + kprintf("[EXT2] Invalid block size %u (must be power of 2, 1024-4096)\n", em->block_size); kfree(em); return result; } @@ -1475,16 +1489,46 @@ vfs_mount_result_t ext2_mount(block_device_t* bdev, uint32_t partition_lba) { if (sb.s_rev_level >= 1 && sb.s_inode_size != 0) { em->inode_size = sb.s_inode_size; + /* Validate inode size is reasonable */ + if (em->inode_size < 128 || em->inode_size > 4096) { + kprintf("[EXT2] Invalid inode size %u\n", em->inode_size); + kfree(em); + return result; + } } else { em->inode_size = 128; } + /* Validate num_groups calculation doesn't overflow */ + if (sb.s_blocks_per_group == 0) { + kprintf("[EXT2] Division by zero in num_groups calculation\n"); + kfree(em); + return result; + } em->num_groups = (sb.s_blocks_count + sb.s_blocks_per_group - 1) / sb.s_blocks_per_group; /* Read Group Descriptor Table */ + /* Validate gdt_bytes doesn't overflow */ + if (em->num_groups > 65536) { /* Reasonable limit for num_groups */ + kprintf("[EXT2] Invalid num_groups: %u\n", em->num_groups); + kfree(em); + return result; + } em->gdt_blocks = (em->num_groups * (uint32_t)sizeof(struct ext2_group_desc) + em->block_size - 1) / em->block_size; uint32_t gdt_bytes = em->num_groups * (uint32_t)sizeof(struct ext2_group_desc); + /* Validate gdt_bytes doesn't overflow and is reasonable */ + if (gdt_bytes > 16 * 1024 * 1024) { /* Max 16MB for GDT */ + kprintf("[EXT2] GDT too large: %u bytes\n", gdt_bytes); + kfree(em); + return result; + } + /* Validate gdt_blocks against device size */ + if (em->gdt_blocks > em->total_blocks) { + kprintf("[EXT2] GDT blocks %u exceed total blocks %u\n", em->gdt_blocks, em->total_blocks); + kfree(em); + return result; + } em->gdt = (struct ext2_group_desc*)kmalloc(gdt_bytes); if (!em->gdt) { kprintf("[EXT2] Failed to allocate GDT (%u bytes)\n", gdt_bytes);