mirror of
https://github.com/qemu/qemu.git
synced 2024-12-02 08:13:34 +08:00
m25p80: don't let rogue SPI controllers cause buffer overruns
In normal operation we should never attempt to put more data into the data[] array than it can hold. However if the SPI controller connected to us misbehaves then it can send us a sequence of commands that attempt this. Since the controller might be in the guest (if the hardware does SPI via bit-banging), catch the possible overrun conditions and reset the flash internal state, logging them as guest errors. Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net> Message-id: 20170107111631.24444-1-jcd@tribudubois.net Reviewed-by: Peter Maydell <peter.maydell@linaro.org> [PMM: rewrote commit message to be more exact about when this can happen] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
8dd845d3c4
commit
24cb2e0d57
@ -28,6 +28,7 @@
|
|||||||
#include "hw/ssi/ssi.h"
|
#include "hw/ssi/ssi.h"
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
|
||||||
#ifndef M25P80_ERR_DEBUG
|
#ifndef M25P80_ERR_DEBUG
|
||||||
@ -377,6 +378,8 @@ typedef enum {
|
|||||||
MAN_GENERIC,
|
MAN_GENERIC,
|
||||||
} Manufacturer;
|
} Manufacturer;
|
||||||
|
|
||||||
|
#define M25P80_INTERNAL_DATA_BUFFER_SZ 16
|
||||||
|
|
||||||
typedef struct Flash {
|
typedef struct Flash {
|
||||||
SSISlave parent_obj;
|
SSISlave parent_obj;
|
||||||
|
|
||||||
@ -387,7 +390,7 @@ typedef struct Flash {
|
|||||||
int page_size;
|
int page_size;
|
||||||
|
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
uint8_t data[16];
|
uint8_t data[M25P80_INTERNAL_DATA_BUFFER_SZ];
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
uint8_t needed_bytes;
|
uint8_t needed_bytes;
|
||||||
@ -1115,6 +1118,17 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
|
|||||||
|
|
||||||
case STATE_COLLECTING_DATA:
|
case STATE_COLLECTING_DATA:
|
||||||
case STATE_COLLECTING_VAR_LEN_DATA:
|
case STATE_COLLECTING_VAR_LEN_DATA:
|
||||||
|
|
||||||
|
if (s->len >= M25P80_INTERNAL_DATA_BUFFER_SZ) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"M25P80: Write overrun internal data buffer. "
|
||||||
|
"SPI controller (QEMU emulator or guest driver) "
|
||||||
|
"is misbehaving\n");
|
||||||
|
s->len = s->pos = 0;
|
||||||
|
s->state = STATE_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
s->data[s->len] = (uint8_t)tx;
|
s->data[s->len] = (uint8_t)tx;
|
||||||
s->len++;
|
s->len++;
|
||||||
|
|
||||||
@ -1124,6 +1138,17 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_READING_DATA:
|
case STATE_READING_DATA:
|
||||||
|
|
||||||
|
if (s->pos >= M25P80_INTERNAL_DATA_BUFFER_SZ) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"M25P80: Read overrun internal data buffer. "
|
||||||
|
"SPI controller (QEMU emulator or guest driver) "
|
||||||
|
"is misbehaving\n");
|
||||||
|
s->len = s->pos = 0;
|
||||||
|
s->state = STATE_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
r = s->data[s->pos];
|
r = s->data[s->pos];
|
||||||
s->pos++;
|
s->pos++;
|
||||||
if (s->pos == s->len) {
|
if (s->pos == s->len) {
|
||||||
@ -1196,7 +1221,7 @@ static const VMStateDescription vmstate_m25p80 = {
|
|||||||
.pre_save = m25p80_pre_save,
|
.pre_save = m25p80_pre_save,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT8(state, Flash),
|
VMSTATE_UINT8(state, Flash),
|
||||||
VMSTATE_UINT8_ARRAY(data, Flash, 16),
|
VMSTATE_UINT8_ARRAY(data, Flash, M25P80_INTERNAL_DATA_BUFFER_SZ),
|
||||||
VMSTATE_UINT32(len, Flash),
|
VMSTATE_UINT32(len, Flash),
|
||||||
VMSTATE_UINT32(pos, Flash),
|
VMSTATE_UINT32(pos, Flash),
|
||||||
VMSTATE_UINT8(needed_bytes, Flash),
|
VMSTATE_UINT8(needed_bytes, Flash),
|
||||||
|
Loading…
Reference in New Issue
Block a user