diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2020-10-22 11:13:24 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2020-10-22 11:13:25 +0100 |
| commit | eec4682e9977ea4e57d7238fba2782e6f2f3b0d0 (patch) | |
| tree | 3e8dc5a34291c075167d071af671b0e15ea1a835 /hw/sd/sd.c | |
| parent | 02aa56c4bc409d5822d39e734fc13a2b26cdd171 (diff) | |
| parent | 84816fb63e5c57159b469a66052d1b2bc862ef77 (diff) | |
| download | focaccia-qemu-eec4682e9977ea4e57d7238fba2782e6f2f3b0d0.tar.gz focaccia-qemu-eec4682e9977ea4e57d7238fba2782e6f2f3b0d0.zip | |
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/sd-next-20201021' into staging
SD/MMC patches Fix two heap-overflow reported by Alexander Bulekov while fuzzing: - https://bugs.launchpad.net/qemu/+bug/1892960 - https://bugs.launchpad.net/qemu/+bug/1895310 CI jobs results: . https://cirrus-ci.com/build/6399328187056128 . https://gitlab.com/philmd/qemu/-/pipelines/205701966 . https://travis-ci.org/github/philmd/qemu/builds/737708930 # gpg: Signature made Wed 21 Oct 2020 18:33:08 BST # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full] # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * remotes/philmd-gitlab/tags/sd-next-20201021: hw/sd/sdcard: Assert if accessing an illegal group hw/sd/sdcard: Do not attempt to erase out of range addresses hw/sd/sdcard: Reset both start/end addresses on error hw/sd/sdcard: Do not use legal address '0' for INVALID_ADDRESS hw/sd/sdcard: Introduce the INVALID_ADDRESS definition hw/sd/sdcard: Add trace event for ERASE command (CMD38) hw/sd/sdhci: Yield if interrupt delivered during multiple transfer hw/sd/sdhci: Let sdhci_update_irq() return if IRQ was delivered hw/sd/sdhci: Resume pending DMA transfers on MMIO accesses hw/sd/sdhci: Stop multiple transfers when block count is cleared hw/sd/sdhci: Fix DMA Transfer Block Size field hw/sd/sdhci: Document the datasheet used hw/sd/sdhci: Fix qemu_log_mask() format string Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/sd/sd.c')
| -rw-r--r-- | hw/sd/sd.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 0012882222..c3febed243 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -53,6 +53,8 @@ #define SDSC_MAX_CAPACITY (2 * GiB) +#define INVALID_ADDRESS UINT32_MAX + typedef enum { sd_r0 = 0, /* no response */ sd_r1, /* normal response command */ @@ -575,8 +577,8 @@ static void sd_reset(DeviceState *dev) sd->wpgrps_size = sect; sd->wp_groups = bitmap_new(sd->wpgrps_size); memset(sd->function_group, 0, sizeof(sd->function_group)); - sd->erase_start = 0; - sd->erase_end = 0; + sd->erase_start = INVALID_ADDRESS; + sd->erase_end = INVALID_ADDRESS; sd->size = size; sd->blk_len = 0x200; sd->pwd_len = 0; @@ -664,8 +666,8 @@ static int sd_vmstate_pre_load(void *opaque) static const VMStateDescription sd_vmstate = { .name = "sd-card", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .pre_load = sd_vmstate_pre_load, .fields = (VMStateField[]) { VMSTATE_UINT32(mode, SDState), @@ -749,9 +751,12 @@ static void sd_erase(SDState *sd) uint64_t erase_start = sd->erase_start; uint64_t erase_end = sd->erase_end; - trace_sdcard_erase(); - if (!sd->erase_start || !sd->erase_end) { + trace_sdcard_erase(sd->erase_start, sd->erase_end); + if (sd->erase_start == INVALID_ADDRESS + || sd->erase_end == INVALID_ADDRESS) { sd->card_status |= ERASE_SEQ_ERROR; + sd->erase_start = INVALID_ADDRESS; + sd->erase_end = INVALID_ADDRESS; return; } @@ -761,13 +766,21 @@ static void sd_erase(SDState *sd) erase_end *= 512; } + if (sd->erase_start > sd->size || sd->erase_end > sd->size) { + sd->card_status |= OUT_OF_RANGE; + sd->erase_start = INVALID_ADDRESS; + sd->erase_end = INVALID_ADDRESS; + return; + } + erase_start = sd_addr_to_wpnum(erase_start); erase_end = sd_addr_to_wpnum(erase_end); - sd->erase_start = 0; - sd->erase_end = 0; + sd->erase_start = INVALID_ADDRESS; + sd->erase_end = INVALID_ADDRESS; sd->csd[14] |= 0x40; for (i = erase_start; i <= erase_end; i++) { + assert(i < sd->wpgrps_size); if (test_bit(i, sd->wp_groups)) { sd->card_status |= WP_ERASE_SKIP; } @@ -782,6 +795,7 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) wpnum = sd_addr_to_wpnum(addr); for (i = 0; i < 32; i++, wpnum++, addr += WPGROUP_SIZE) { + assert(wpnum < sd->wpgrps_size); if (addr < sd->size && test_bit(wpnum, sd->wp_groups)) { ret |= (1 << i); } |