if (mbi_phys) {
uint32_t total_size = *(volatile uint32_t*)mbi_phys;
+ /* A15: Validate total_size is reasonable */
+ if (total_size < 8 || total_size > 65536) {
+ kprintf("[WARN] Invalid Multiboot2 total_size: %u\n", total_size);
+ total_size = 8; /* Use minimum valid size */
+ }
if (total_size >= 8) {
multiboot_copy_size = total_size;
if (multiboot_copy_size > sizeof(multiboot_copy)) {
if (bi.arch_boot_info) {
struct multiboot_tag* tag;
- for (tag = (struct multiboot_tag*)((uint8_t*)bi.arch_boot_info + 8);
- tag->type != MULTIBOOT_TAG_TYPE_END;
- tag = (struct multiboot_tag*)((uint8_t*)tag + ((tag->size + 7) & ~7))) {
+ uint32_t cursor = 8; /* Skip header */
+ while (cursor + 8 <= multiboot_copy_size) {
+ tag = (struct multiboot_tag*)((uint8_t*)bi.arch_boot_info + cursor);
+
+ /* A15: Validate tag size */
+ if (tag->size < 8) {
+ kprintf("[WARN] Invalid Multiboot2 tag size: %u\n", tag->size);
+ break;
+ }
+ if (cursor + tag->size > multiboot_copy_size) {
+ kprintf("[WARN] Multiboot2 tag exceeds buffer\n");
+ break;
+ }
+
+ if (tag->type == MULTIBOOT_TAG_TYPE_END) break;
+
if (tag->type == MULTIBOOT_TAG_TYPE_MODULE) {
const struct multiboot_tag_module* mod = (const struct multiboot_tag_module*)tag;
if (!bi.initrd_start) {
bi.fb_bpp = fb->framebuffer_bpp;
bi.fb_type = fb->framebuffer_type;
}
+
+ /* A15: Advance to next tag (8-byte aligned) */
+ cursor += (tag->size + 7) & ~7;
}
}
struct ext2_dir_entry* de = (struct ext2_dir_entry*)(blk_buf + off);
if (de->rec_len == 0) goto done;
+ /* F01: Validate rec_len */
+ if (de->rec_len < 8) goto done;
+ if (de->rec_len % 4 != 0) goto done;
+ if (off + de->rec_len > bs) goto done;
+ /* F01: Validate name_len */
+ if (de->name_len >= de->rec_len - 8) goto done;
+
if (de->inode != 0 && de->name_len == name_len) {
if (memcmp(de->name, name, name_len) == 0) {
struct ext2_inode child_inode;
struct ext2_dir_entry* de = (struct ext2_dir_entry*)(blk_buf + off);
if (de->rec_len == 0) goto done;
+ /* F01: Validate rec_len */
+ if (de->rec_len < 8) goto done;
+ if (de->rec_len % 4 != 0) goto done;
+ if (off + de->rec_len > bs) goto done;
+ /* F01: Validate name_len */
+ if (de->name_len >= de->rec_len - 8) goto done;
+
if (de->inode != 0) {
/* Skip . and .. */
int skip = 0;
struct ext2_dir_entry* de = (struct ext2_dir_entry*)(blk_buf + off);
if (de->rec_len == 0) break;
+ /* F01: Validate rec_len */
+ if (de->rec_len < 8) break;
+ if (de->rec_len % 4 != 0) break;
+ if (off + de->rec_len > bs) break;
+ /* F01: Validate name_len */
+ if (de->name_len >= de->rec_len - 8) break;
+
uint32_t actual_len = ((uint32_t)sizeof(struct ext2_dir_entry) + de->name_len + 3) & ~3U;
uint32_t free_space = de->rec_len - actual_len;
struct ext2_dir_entry* de = (struct ext2_dir_entry*)(blk_buf + off);
if (de->rec_len == 0) break;
+ /* F01: Validate rec_len */
+ if (de->rec_len < 8) break;
+ if (de->rec_len % 4 != 0) break;
+ if (off + de->rec_len > bs) break;
+ /* F01: Validate name_len */
+ if (de->name_len >= de->rec_len - 8) break;
+
if (de->inode != 0 && de->name_len == name_len &&
memcmp(de->name, name, name_len) == 0) {
if (removed_ino) *removed_ino = de->inode;
struct ext2_dir_entry* de = (struct ext2_dir_entry*)(blk_buf + off);
if (de->rec_len == 0) goto not_found;
+ /* F01: Validate rec_len */
+ if (de->rec_len < 8) goto not_found;
+ if (de->rec_len % 4 != 0) goto not_found;
+ if (off + de->rec_len > bs) goto not_found;
+ /* F01: Validate name_len */
+ if (de->name_len >= de->rec_len - 8) goto not_found;
+
if (de->inode != 0 && de->name_len == name_len &&
memcmp(de->name, name, name_len) == 0) {
if (out_ino) *out_ino = de->inode;
struct ext2_dir_entry* de = (struct ext2_dir_entry*)(blk_buf + off);
if (de->rec_len == 0) return 1;
+ /* F01: Validate rec_len */
+ if (de->rec_len < 8) return 1;
+ if (de->rec_len % 4 != 0) return 1;
+ if (off + de->rec_len > bs) return 1;
+ /* F01: Validate name_len */
+ if (de->name_len >= de->rec_len - 8) return 1;
+
if (de->inode != 0) {
int is_dot = (de->name_len == 1 && de->name[0] == '.');
int is_dotdot = (de->name_len == 2 && de->name[0] == '.' && de->name[1] == '.');