diff --git a/usr.sbin/installboot/arch/i386.c b/usr.sbin/installboot/arch/i386.c index a18a903900be..27e569362956 100644 --- a/usr.sbin/installboot/arch/i386.c +++ b/usr.sbin/installboot/arch/i386.c @@ -418,8 +418,18 @@ i386_setboot(ib_params *params) return 0; } - /* Find size of old BPB, and copy into new bootcode */ - if (!is_zero(disk_buf.b + 3 + 8, disk_buf.b[1] - 1 - 8)) { + /* + * Find size of old BPB, and copy into new bootcode + * + * The 2nd byte (b[1]) contains jmp short relative offset. + * If it is zero or some invalid input that is smaller than 9, + * it will cause overflow and call is_zero() with enormous size. + * Add a paranoid check to prevent this scenario. + * + * Verify that b[0] contains JMP (0xeb) and b[2] NOP (0x90). + */ + if (disk_buf.b[0] == 0xeb && disk_buf.b[1] >= 9 && disk_buf.b[2] == 0x90 && + !is_zero(disk_buf.b + 3 + 8, (unsigned char)disk_buf.b[1] - 1 - 8)) { struct mbr_bpbFAT16 *bpb = (void *)(disk_buf.b + 3 + 8); /* Check enough space before the FAT for the bootcode */ u = le16toh(bpb->bpbBytesPerSec)