U-Boot scans the partitions of a block device as soon as it probes it, and takes several sizes from the device and from its partition tables as they are. A USB stick or SD card that U-Boot merely probes can therefore make it read or write outside its buffers. This series checks those sizes where they are read.
Block size. A block driver sets the block size of a device from what the device reports, and only the virtio block driver and the host command check it. The partition and filesystem code sizes buffers by the block size, expects a block to hold a 512-byte boot sector and converts between bytes and blocks with log2(blksz). So a USB stick, SCSI disk, ATAPI drive or NVMe namespace reporting a block size below 512 bytes, one that is not a power of two or a huge one makes U-Boot read or write outside its buffers, in the partition scan run when the device is probed and in the filesystem code after it. Patch 1 drops two local copies of is_power_of_2(), so that blk.h can use the one in linux/log2.h, and patch 2 adds blk_valid_blksz() there. Patch 3 fixes the reply the USB storage driver makes up when READ CAPACITY fails, which gave a 128KiB block size on a little-endian host. Patches 4-7 check the block size where the USB storage, SCSI, IDE (ATAPI) and NVMe drivers read it, so that each refuses such a device cleanly: the USB LUN is skipped instead of failing the whole stick, no SCSI block device is created, the ATAPI drive is treated as one without a medium and the NVMe namespace is skipped like an inactive one. Patch 8 then has blk_post_probe() refuse a block device whose block size blk_valid_blksz() rejects, which covers every block driver when its device is probed, outside SPL and TPL (their size limits leave no room for it). The MMC code sets the block size of a card again when it initialises the card anew, as "mmc rescan" does; a follow-up will check it there. The upper bound is 64KiB, the largest logical block size Linux accepts; the GPT code is already tested with block sizes up to 32KiB. Partition tables. Patch 9 checks the header size and the size of the partition entry array of a GPT, as Linux does, before they size the CRC of the header and the entry buffer. It leaves alloc_read_gpt_entries() alone, so it applies with or without BenoƮt Monin's "disk: efi: Reuse the GPT entries buffer with simple malloc". Patch 10 walks the chain of DOS extended partition tables in a loop: a table linking back to itself adds no partition, so the limit added for CVE-2019-13103 did not stop the recursion. As Linux does, the walk now gives up after a few tables in a row that hold no partition. Patch 11 makes room for partition number 256 in the UUID made up for a DOS partition. Patch 12 has the TCG2 measurement of the GPT measure the GPT the partition driver uses, read with the driver's own code. It read the primary GPT itself, unchecked, while the driver falls back to the backup GPT when the primary one is not valid, so PCR 5 could hold a GPT the partitions were not found in, and the sizes in an unchecked header could make the measurement read past its buffer. Patches 4, 5 and 8-12 add tests: DM tests on sandbox, for the GPT a test in test/lib on a blkmap device, and for the TCG2 measurement a test in test/py that starts an EFI application from a GPT disk on sandbox and checks PCR 5. With the series they pass, as do the rest of "ut dm" and "ut lib" on sandbox_defconfig with CONFIG_ASAN (but for lib_crypt, which ASan flags without the series too), and each patch builds and passes the tests present so far on its own. The test/py test is skipped with CONFIG_ASAN, under which sandbox cannot run an EFI application; on sandbox_defconfig it passes, as do the other EFI, TPM and GPT tests in test/py. The IDE and NVMe changes are build tested only, as sandbox has no emulator for them. CI: stacked with my other three series under review, the series passes all 91 jobs of U-Boot's Azure pipeline, in build 13698 of my CI-only pull request. Its first run, build 13695, showed the SPL cost of the blk_post_probe() check on the boards named in the changes below. PR: https://github.com/u-boot/u-boot/pull/1064 Build: https://dev.azure.com/u-boot/u-boot/_build/results?buildId=13698 Changes in v2: - Reorder the block size patches, so that each step is bisectable: the helper first, then the driver patches, and the blk_post_probe() check last (Simon) - Use is_power_of_2() in blk_valid_blksz() (Simon), after a new patch 1 that drops the local copies in the btrfs code and bcm2835_sdhost, which clash with it - Split the USB READ CAPACITY fallback fix into a patch of its own, with a Fixes: tag, and fake 2880 blocks rather than 2881 (Simon) - Name the LUN that the USB storage driver skips, and check the message in the test (Simon) - Take the ATAPI block sizes 0, 2340 and 2352 as 2048, as Linux does, and say what is skipped otherwise (Simon) - Leave the blk_post_probe() check out of SPL and TPL, where it took the SPL of imx28_btt3 and popmetal-rk3288 over their size limits and broke the link of evb-rk3036's, and say why it is outside the PARTITIONS condition (Simon) - Include linux/sizes.h in part_efi.c, and word the GPT commit message so that the fastboot path is not taken as fully covered (Simon) - Write the DOS walk as a for loop with a helper that follows the links, and stop it after 16 tables in a row without a partition (Simon) - Measure the GPT the partition driver uses, which checks the CRC of the entries too (Simon), and when the primary GPT is not valid the backup one, with the primary header made from it, as EDK2 does (Ilias); say what the bug does to PCR 5 (Ilias) - Avoid ut_assertok() of a known -ENOMEM in the GPT test (Coverity) Ana Bobillo (12): treewide: Use is_power_of_2() from linux/log2.h block: Add blk_valid_blksz() to check a block size usb: storage: Fix the capacity faked when READ CAPACITY fails usb: storage: Refuse a block size the block layer cannot use scsi: Refuse a block size the block layer cannot use ide: Refuse an ATAPI block size atapi_read() cannot read nvme: Skip a namespace with an unsupported LBA data size block: Refuse a device with an unsupported block size disk: part_efi: Check the header and entry sizes of a GPT disk: part_dos: Walk the extended partition tables in a bounded loop disk: part_dos: Make room for a three-digit partition number in the UUID efi_loader: Measure the GPT the partition driver uses arch/sandbox/include/asm/test.h | 20 +++ cmd/host.c | 5 +- common/usb_storage.c | 10 +- disk/part_dos.c | 291 ++++++++++++++++++------------- disk/part_efi.c | 68 +++++++- drivers/block/blk-uclass.c | 15 ++ drivers/block/ide.c | 23 ++- drivers/mmc/bcm2835_sdhost.c | 6 +- drivers/nvme/nvme.c | 33 +++- drivers/scsi/sandbox_scsi.c | 8 + drivers/scsi/scsi.c | 4 + drivers/usb/emul/sandbox_flash.c | 8 + drivers/virtio/virtio_blk.c | 2 +- fs/btrfs/compat.h | 6 +- include/blk.h | 21 +++ include/part.h | 26 +++ lib/efi_loader/efi_tcg2.c | 51 +++--- test/dm/blk.c | 41 +++++ test/dm/part.c | 221 +++++++++++++++++++++++ test/dm/scsi.c | 37 ++++ test/dm/usb.c | 51 ++++++ test/lib/part_efi.c | 203 +++++++++++++++++++++ test/py/tests/test_efi_tcg2.py | 222 +++++++++++++++++++++++ 23 files changed, 1198 insertions(+), 174 deletions(-) create mode 100644 test/py/tests/test_efi_tcg2.py base-commit: dfcfc4c9f78d1743f490a497082a4ec8e058aae8
