Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/cohuck-gitlab/tags/s390x-202104…
Browse files Browse the repository at this point in the history
…09' into staging

One s390x fix:
- correctly handle the case where the guest ccw payload points to
  invalid memory areas

# gpg: Signature made Fri 09 Apr 2021 15:43:45 BST
# gpg:                using RSA key C3D0D66DC3624FF6A8C018CEDECF6B93C6F02FAF
# gpg:                issuer "cohuck@redhat.com"
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>" [unknown]
# gpg:                 aka "Cornelia Huck <huckc@linux.vnet.ibm.com>" [full]
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>" [full]
# gpg:                 aka "Cornelia Huck <cohuck@kernel.org>" [unknown]
# gpg:                 aka "Cornelia Huck <cohuck@redhat.com>" [unknown]
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck-gitlab/tags/s390x-20210409:
  s390x: css: report errors from ccw_dstream_read/write

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Apr 9, 2021
2 parents 285f6f5 + d895d25 commit 471387a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 27 deletions.
11 changes: 9 additions & 2 deletions hw/char/terminal3270.c
Expand Up @@ -200,9 +200,13 @@ static int read_payload_3270(EmulatedCcw3270Device *dev)
{
Terminal3270 *t = TERMINAL_3270(dev);
int len;
int ret;

len = MIN(ccw_dstream_avail(get_cds(t)), t->in_len);
ccw_dstream_write_buf(get_cds(t), t->inv, len);
ret = ccw_dstream_write_buf(get_cds(t), t->inv, len);
if (ret < 0) {
return ret;
}
t->in_len -= len;

return len;
Expand Down Expand Up @@ -260,7 +264,10 @@ static int write_payload_3270(EmulatedCcw3270Device *dev, uint8_t cmd)

t->outv[out_len++] = cmd;
do {
ccw_dstream_read_buf(get_cds(t), &t->outv[out_len], len);
retval = ccw_dstream_read_buf(get_cds(t), &t->outv[out_len], len);
if (retval < 0) {
return retval;
}
count = ccw_dstream_avail(get_cds(t));
out_len += len;

Expand Down
5 changes: 4 additions & 1 deletion hw/s390x/3270-ccw.c
Expand Up @@ -31,6 +31,9 @@ static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
}

len = ck->read_payload_3270(dev);
if (len < 0) {
return len;
}
ccw_dev->sch->curr_status.scsw.count = ccw->count - len;

return 0;
Expand All @@ -50,7 +53,7 @@ static int handle_payload_3270_write(EmulatedCcw3270Device *dev, CCW1 *ccw)
len = ck->write_payload_3270(dev, ccw->cmd_code);

if (len <= 0) {
return -EIO;
return len ? len : -EIO;
}

ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
Expand Down
14 changes: 8 additions & 6 deletions hw/s390x/css.c
Expand Up @@ -1055,10 +1055,11 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
}
}
len = MIN(ccw.count, sizeof(sch->sense_data));
ccw_dstream_write_buf(&sch->cds, sch->sense_data, len);
ret = ccw_dstream_write_buf(&sch->cds, sch->sense_data, len);
sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
memset(sch->sense_data, 0, sizeof(sch->sense_data));
ret = 0;
if (!ret) {
memset(sch->sense_data, 0, sizeof(sch->sense_data));
}
break;
case CCW_CMD_SENSE_ID:
{
Expand All @@ -1083,9 +1084,10 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
} else {
sense_id[0] = 0;
}
ccw_dstream_write_buf(&sch->cds, sense_id, len);
sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
ret = 0;
ret = ccw_dstream_write_buf(&sch->cds, sense_id, len);
if (!ret) {
sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
}
break;
}
case CCW_CMD_TIC:
Expand Down
66 changes: 48 additions & 18 deletions hw/s390x/virtio-ccw.c
Expand Up @@ -288,14 +288,20 @@ static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
return -EFAULT;
}
if (is_legacy) {
ccw_dstream_read(&sch->cds, linfo);
ret = ccw_dstream_read(&sch->cds, linfo);
if (ret) {
return ret;
}
linfo.queue = be64_to_cpu(linfo.queue);
linfo.align = be32_to_cpu(linfo.align);
linfo.index = be16_to_cpu(linfo.index);
linfo.num = be16_to_cpu(linfo.num);
ret = virtio_ccw_set_vqs(sch, NULL, &linfo);
} else {
ccw_dstream_read(&sch->cds, info);
ret = ccw_dstream_read(&sch->cds, info);
if (ret) {
return ret;
}
info.desc = be64_to_cpu(info.desc);
info.index = be16_to_cpu(info.index);
info.num = be16_to_cpu(info.num);
Expand Down Expand Up @@ -371,7 +377,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);

ccw_dstream_advance(&sch->cds, sizeof(features.features));
ccw_dstream_read(&sch->cds, features.index);
ret = ccw_dstream_read(&sch->cds, features.index);
if (ret) {
break;
}
if (features.index == 0) {
if (dev->revision >= 1) {
/* Don't offer legacy features for modern devices. */
Expand All @@ -392,9 +401,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
}
ccw_dstream_rewind(&sch->cds);
features.features = cpu_to_le32(features.features);
ccw_dstream_write(&sch->cds, features.features);
sch->curr_status.scsw.count = ccw.count - sizeof(features);
ret = 0;
ret = ccw_dstream_write(&sch->cds, features.features);
if (!ret) {
sch->curr_status.scsw.count = ccw.count - sizeof(features);
}
}
break;
case CCW_CMD_WRITE_FEAT:
Expand All @@ -411,7 +421,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) {
ret = -EFAULT;
} else {
ccw_dstream_read(&sch->cds, features);
ret = ccw_dstream_read(&sch->cds, features);
if (ret) {
break;
}
features.features = le32_to_cpu(features.features);
if (features.index == 0) {
virtio_set_features(vdev,
Expand Down Expand Up @@ -454,9 +467,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
virtio_bus_get_vdev_config(&dev->bus, vdev->config);
ccw_dstream_write_buf(&sch->cds, vdev->config, len);
sch->curr_status.scsw.count = ccw.count - len;
ret = 0;
ret = ccw_dstream_write_buf(&sch->cds, vdev->config, len);
if (ret) {
sch->curr_status.scsw.count = ccw.count - len;
}
}
break;
case CCW_CMD_WRITE_CONF:
Expand Down Expand Up @@ -511,7 +525,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) {
ret = -EFAULT;
} else {
ccw_dstream_read(&sch->cds, status);
ret = ccw_dstream_read(&sch->cds, status);
if (ret) {
break;
}
if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
virtio_ccw_stop_ioeventfd(dev);
}
Expand Down Expand Up @@ -554,7 +571,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) {
ret = -EFAULT;
} else {
ccw_dstream_read(&sch->cds, indicators);
ret = ccw_dstream_read(&sch->cds, indicators);
if (ret) {
break;
}
indicators = be64_to_cpu(indicators);
dev->indicators = get_indicator(indicators, sizeof(uint64_t));
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
Expand All @@ -575,7 +595,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) {
ret = -EFAULT;
} else {
ccw_dstream_read(&sch->cds, indicators);
ret = ccw_dstream_read(&sch->cds, indicators);
if (ret) {
break;
}
indicators = be64_to_cpu(indicators);
dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
Expand All @@ -596,7 +619,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) {
ret = -EFAULT;
} else {
ccw_dstream_read(&sch->cds, vq_config.index);
ret = ccw_dstream_read(&sch->cds, vq_config.index);
if (ret) {
break;
}
vq_config.index = be16_to_cpu(vq_config.index);
if (vq_config.index >= VIRTIO_QUEUE_MAX) {
ret = -EINVAL;
Expand All @@ -605,9 +631,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
vq_config.num_max = virtio_queue_get_num(vdev,
vq_config.index);
vq_config.num_max = cpu_to_be16(vq_config.num_max);
ccw_dstream_write(&sch->cds, vq_config.num_max);
sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
ret = 0;
ret = ccw_dstream_write(&sch->cds, vq_config.num_max);
if (!ret) {
sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
}
}
break;
case CCW_CMD_SET_IND_ADAPTER:
Expand Down Expand Up @@ -664,7 +691,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
break;
}
ccw_dstream_read_buf(&sch->cds, &revinfo, 4);
ret = ccw_dstream_read_buf(&sch->cds, &revinfo, 4);
if (ret < 0) {
break;
}
revinfo.revision = be16_to_cpu(revinfo.revision);
revinfo.length = be16_to_cpu(revinfo.length);
if (ccw.count < len + revinfo.length ||
Expand Down

0 comments on commit 471387a

Please sign in to comment.