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;
}
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);