From: Prasad J Pandit <p...@fedoraproject.org> Set an upper limit to number of sectors on an IDE disk media. This is to ensure that logical block addresses (LBA) and nb_sector arguments remain within INT_MAX range.
Suggested-by: Paolo Bonzini <pbonz...@redhat.com> Signed-off-by: Prasad J Pandit <p...@fedoraproject.org> --- hw/ide/core.c | 27 ++++++++++++++++----------- include/hw/ide/internal.h | 1 + 2 files changed, 17 insertions(+), 11 deletions(-) Update v2: add explanatory comment, define macro -> https://lists.gnu.org/archive/html/qemu-devel/2021-01/msg04610.html Update v1: limit s->nb_sectors count -> https://lists.gnu.org/archive/html/qemu-devel/2021-01/msg04270.html -> https://lists.gnu.org/archive/html/qemu-devel/2021-01/msg04173.html diff --git a/hw/ide/core.c b/hw/ide/core.c index b49e4cfbc6..902f51423d 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -1161,15 +1161,25 @@ static void ide_cfata_metadata_write(IDEState *s) s->nsector << 9), 0x200 - 2)); } +static void ide_set_nb_sectors(IDEState *s) +{ + uint64_t nb_sectors; + blk_get_geometry(s->blk, &nb_sectors); + + /* + * Restrict total number of addressable sectors to (INT_MAX << 2), + * so that logical addresses (LBA) stay within INT_MAX limit. + */ + s->nb_sectors = MIN(nb_sectors, IDE_MAX_NB_SECTORS); +} + /* called when the inserted state of the media has changed */ static void ide_cd_change_cb(void *opaque, bool load, Error **errp) { IDEState *s = opaque; - uint64_t nb_sectors; s->tray_open = !load; - blk_get_geometry(s->blk, &nb_sectors); - s->nb_sectors = nb_sectors; + ide_set_nb_sectors(s); /* * First indicate to the guest that a CD has been removed. That's @@ -2475,14 +2485,12 @@ static bool ide_cd_is_medium_locked(void *opaque) static void ide_resize_cb(void *opaque) { IDEState *s = opaque; - uint64_t nb_sectors; if (!s->identify_set) { return; } - blk_get_geometry(s->blk, &nb_sectors); - s->nb_sectors = nb_sectors; + ide_set_nb_sectors(s); /* Update the identify data buffer. */ if (s->drive_kind == IDE_CFATA) { @@ -2511,17 +2519,14 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, uint32_t cylinders, uint32_t heads, uint32_t secs, int chs_trans, Error **errp) { - uint64_t nb_sectors; - s->blk = blk; s->drive_kind = kind; - - blk_get_geometry(blk, &nb_sectors); s->cylinders = cylinders; s->heads = heads; s->sectors = secs; s->chs_trans = chs_trans; - s->nb_sectors = nb_sectors; + ide_set_nb_sectors(s); + s->wwn = wwn; /* The SMART values should be preserved across power cycles but they aren't. */ diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h index 2d09162eeb..7c436def5b 100644 --- a/include/hw/ide/internal.h +++ b/include/hw/ide/internal.h @@ -219,6 +219,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(IDEBus, IDE_BUS) /* set to 1 set disable mult support */ #define MAX_MULT_SECTORS 16 +#define IDE_MAX_NB_SECTORS ((uint64_t)INT_MAX << 2) #define IDE_DMA_BUF_SECTORS 256 /* feature values for Data Set Management */ -- 2.29.2