[Bug 197881] boot1.efi UEFI system table corruption
bugzilla-noreply at freebsd.org
bugzilla-noreply at freebsd.org
Sat Feb 21 16:51:33 UTC 2015
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=197881
Bug ID: 197881
Summary: boot1.efi UEFI system table corruption
Product: Base System
Version: 10.1-RELEASE
Hardware: Any
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: freebsd-bugs at FreeBSD.org
Reporter: cmruffin at gmail.com
boot1.efi from 10.1-RELEASE can cause data corruption of its own UEFI system
table pointer in memory.
The EfiBlockIoProtocol instance associated with a CDROM parition typically has
a block size of 2048. boot1.efi assumes a block size of 512 in the call to
dskread() to read the superblock, yet the dskread() function in boot1.efi uses
the block size from the BlockIoProtocol instance. This causes the call to
BlkIoProtocol->ReadBlocks() in dskread() to expose a larger-than-actual buffer
size to UEFI FW, which will cause the ReadBlocks() call to overrun the dmadat
buffer.
So if a partition is present in the system with a block size of 2048 (such as
cdrom media partitions), boot1.efi can overrun its dmadat structure and cause
corruption of other global data including a global pointe r to the UEFI system
table.
Failure sequence:
1) dmadat.sbbuf is allocated 8192 bytes at build time (SBLOCKSIZE)
2) Boot1.efi retrieves handles with all instances of BlockIoProtocol.
3) If cdrom partition is present in the system, UEFI FW will return a
BlockIoProtocol of the CDROM partition which has a
BlockIoProtocol->Media->BlockSize = 2048.
4) domount() is called for this BlockIoProtocol instance.
5) fsread() is called to read the superblock
6) Boot1.efi dskread() is called with nblk=16 (fixed SBLOCKSIZE (8192) /
fixed DEV_BSIZE (512)). This is assuming a block size of 512.
7) dskread() in boot1.efi calls
status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba,
nblk * bootdev->Media->BlockSize, buf);
Here nblk=16 but bootdev->Media->BlockSize is 2048 which results in passing
a Buffer Size argument of 16 * 2048 = 32768 which overruns the dmadat->sbbuf
fixed allocation.
8) UEFI ReaadBlocks() overruns dmadat and overwrites the global pointer to
the UEFI system table (sets it to zero)
9) A subsequent call to systab->BootServices->HandleProtocol() causes path
of exeution at physical address 0x98 which does not contain valid code.
10) Processor eventually raises an invalid opcode exception.
--
You are receiving this mail because:
You are the assignee for the bug.
More information about the freebsd-bugs
mailing list