--- a/sys/kern/subr_diskmbr.c +++ b/sys/kern/subr_diskmbr.c @@ -117,6 +117,16 @@ */ if (info->d_media_blksize & DEV_BMASK) return (EIO); + /* + * The block size comes from the device (e.g. SCSI READ CAPACITY) + * and must never be trusted: mbrinit() issues a synchronous read + * of exactly one media block into a getpbuf_mem() pbuf whose + * buffer is only MAXPHYS bytes. Reject anything that cannot fit + * (also rejects negative/0 values; d_media_blksize is signed). + */ + if (info->d_media_blksize < DEV_BSIZE || + info->d_media_blksize > MAXPHYS) + return (EIO); if (info->d_media_size == 0) return (EIO); @@ -175,10 +185,18 @@ if (bootverbose) kprintf("%s: Found \"Ontrack Disk Manager\" " "on this disk.\n", sname); - bp->b_flags |= B_INVAL | B_AGE; - brelse(bp); - mbr_offset = 63; - goto reread_mbr; + /* + * bp is a pbuf (getpbuf_mem) and must be + * released with relpbuf(), not brelse(). + * Only take the re-read path once, otherwise + * a crafted MBR with another Ontrack entry at + * LBA 63 loops forever. + */ + if (mbr_offset == DOSBBSECTOR) { + relpbuf(bp, NULL); + mbr_offset = 63; + goto reread_mbr; + } } }