summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2019-09-05 19:31:23 +0200
committerHeinrich Schuchardt <xypron.glpk@gmx.de>2019-09-05 23:18:51 +0200
commitf59f0825e8b9fdeb8abe43ffd10c5119ca1a032f (patch)
tree31c50f20cd10dad12634c02da52df085d8f7c3d0 /lib
parent03446987c5008fd1e3732b01fd63a29c7a6d9246 (diff)
efi_loader: parameter checks BLOCK_IO_PROTOCOL
Check parameters of ReadBlocks() and WriteBlocks(). If the buffer size is not a multiple of the block size, we have to return EFI_BAD_BUFFER_SIZE. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/efi_disk.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 7a6b06821a..0bf436ac66 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -74,7 +74,7 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this,
/* We only support full block access */
if (buffer_size & (blksz - 1))
- return EFI_DEVICE_ERROR;
+ return EFI_BAD_BUFFER_SIZE;
if (direction == EFI_DISK_READ)
n = blk_dread(desc, lba, blocks, buffer);
@@ -99,6 +99,20 @@ static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this,
void *real_buffer = buffer;
efi_status_t r;
+ if (!this)
+ return EFI_INVALID_PARAMETER;
+ /* TODO: check for media changes */
+ if (media_id != this->media->media_id)
+ return EFI_MEDIA_CHANGED;
+ if (!this->media->media_present)
+ return EFI_NO_MEDIA;
+ /* media->io_align is a power of 2 */
+ if ((uintptr_t)buffer & (this->media->io_align - 1))
+ return EFI_INVALID_PARAMETER;
+ if (lba * this->media->block_size + buffer_size >
+ this->media->last_block * this->media->block_size)
+ return EFI_INVALID_PARAMETER;
+
#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
r = efi_disk_read_blocks(this, media_id, lba,
@@ -134,6 +148,22 @@ static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this,
void *real_buffer = buffer;
efi_status_t r;
+ if (!this)
+ return EFI_INVALID_PARAMETER;
+ if (this->media->read_only)
+ return EFI_WRITE_PROTECTED;
+ /* TODO: check for media changes */
+ if (media_id != this->media->media_id)
+ return EFI_MEDIA_CHANGED;
+ if (!this->media->media_present)
+ return EFI_NO_MEDIA;
+ /* media->io_align is a power of 2 */
+ if ((uintptr_t)buffer & (this->media->io_align - 1))
+ return EFI_INVALID_PARAMETER;
+ if (lba * this->media->block_size + buffer_size >
+ this->media->last_block * this->media->block_size)
+ return EFI_INVALID_PARAMETER;
+
#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
r = efi_disk_write_blocks(this, media_id, lba,
@@ -288,6 +318,11 @@ static efi_status_t efi_disk_add_dev(
/* Fill in EFI IO Media info (for read/write callbacks) */
diskobj->media.removable_media = desc->removable;
diskobj->media.media_present = 1;
+ /*
+ * MediaID is just an arbitrary counter.
+ * We have to change it if the medium is removed or changed.
+ */
+ diskobj->media.media_id = 1;
diskobj->media.block_size = desc->blksz;
diskobj->media.io_align = desc->blksz;
diskobj->media.last_block = desc->lba - offset;