diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2014-09-05 09:33:18 +0200 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2014-09-23 14:10:17 +0200 |
commit | e8601dd5d0ffa909068ddefe33bf6a53d8af063a (patch) | |
tree | b75f2781b12431b883aa6116e761d61c14f23760 | |
parent | a327c9215d8a9b5935ea807aaa9b65ccd23ec615 (diff) |
s390x/css: catch ccw sequence errors
We must not allow chains of more than 255 ccws without data transfer.
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r-- | hw/s390x/css.c | 10 | ||||
-rw-r--r-- | hw/s390x/css.h | 1 |
2 files changed, 11 insertions, 0 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 34637cb692..b67c039a70 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -294,6 +294,13 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr) check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC)); + if (!ccw.cda) { + if (sch->ccw_no_data_cnt == 255) { + return -EINVAL; + } + sch->ccw_no_data_cnt++; + } + /* Look at the command. */ switch (ccw.cmd_code) { case CCW_CMD_NOOP: @@ -396,6 +403,7 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb) return; } sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT); + sch->ccw_no_data_cnt = 0; } else { s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND); } @@ -1358,6 +1366,7 @@ void subch_device_save(SubchDev *s, QEMUFile *f) qemu_put_be16(f, s->id.ciw[i].count); } qemu_put_byte(f, s->ccw_fmt_1); + qemu_put_byte(f, s->ccw_no_data_cnt); return; } @@ -1414,6 +1423,7 @@ int subch_device_load(SubchDev *s, QEMUFile *f) s->id.ciw[i].count = qemu_get_be16(f); } s->ccw_fmt_1 = qemu_get_byte(f); + s->ccw_no_data_cnt = qemu_get_byte(f); return 0; } diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 384a455aa1..33104ac58e 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -78,6 +78,7 @@ struct SubchDev { bool last_cmd_valid; bool ccw_fmt_1; bool thinint_active; + uint8_t ccw_no_data_cnt; /* transport-provided data: */ int (*ccw_cb) (SubchDev *, CCW1); SenseId id; |