dm: fix the bug that infinite calls to vq_getchain()

The current code would cause infinite calls to vq_getchain()
because that:
  - error check of vq_getchain() return value is missing.
  - virtqueue misunderstand that there are avaliable descripters
    even though the idx of avail ring is invalid.

This patch fixes it by checking validity of the return of
vq_getchain() and jump out of the loop for invalid return value.
This patch alse add validity check in judgment of avaliable
descriptor, and check if the diff between idx of avail ring and
the last idx is greater than size of this queue.

Tracked-On: #7038
Signed-off-by: Wen Qian <qian.wen@intel.com>
Signed-off-by: Li Fei <fei1.li@intel.com>
Acked-by: Wang Yu1 <yu1.wang@intel.com>
This commit is contained in:
Wen Qian 2022-01-18 10:40:01 +08:00 committed by acrnsi-robot
parent c93c2224e0
commit ace5ef44e8
4 changed files with 22 additions and 5 deletions

View File

@ -392,7 +392,10 @@ virtio_console_notify_tx(void *vdev, struct virtio_vq_info *vq)
port = virtio_console_vq_to_port(console, vq);
while (vq_has_descs(vq)) {
vq_getchain(vq, &idx, iov, 1, flags);
if (vq_getchain(vq, &idx, iov, 1, flags) < 1) {
pr_err("%s: fail to getchain!\n", __func__);
break;
}
if ((port != NULL) && (port->cb != NULL))
port->cb(port, port->arg, iov, 1);
@ -481,6 +484,10 @@ virtio_console_backend_read(int fd __attribute__((unused)),
do {
n = vq_getchain(vq, &idx, &iov, 1, NULL);
if (n < 1){
pr_err("%s: fail to getchain!\n", __func__);
break;
}
len = readv(be->fd, &iov, n);
if (len <= 0) {
vq_retchain(vq);

View File

@ -688,7 +688,7 @@ virtio_gpio_notify(void *vdev, struct virtio_vq_info *vq)
gpio = (struct virtio_gpio *)vdev;
if (vq_has_descs(vq)) {
n = vq_getchain(vq, &idx, iov, 2, NULL);
if (n >= 3) {
if (n < 1 || n >= 3) {
WPRINTF(("virtio gpio, invalid chain number %d\n", n));
virtio_gpio_abort(vq, idx);
return;

View File

@ -322,7 +322,10 @@ virtio_rnd_get_entropy(void *param)
pthread_mutex_unlock(&rnd->rx_mtx);
do {
vq_getchain(vq, &idx, &iov, 1, NULL);
if (vq_getchain(vq, &idx, &iov, 1, NULL) < 1) {
pr_err("%s: fail to getchain!\n", __func__);
break;
}
len = read(rnd->fd, iov.iov_base, iov.iov_len);
if (len <= 0) {
vq_retchain(vq);

View File

@ -477,8 +477,15 @@ vq_ring_ready(struct virtio_vq_info *vq)
static inline bool
vq_has_descs(struct virtio_vq_info *vq)
{
return (vq_ring_ready(vq) && vq->last_avail !=
vq->avail->idx);
bool ret = false;
if (vq_ring_ready(vq) && vq->last_avail != vq->avail->idx) {
if ((uint16_t)((u_int)vq->avail->idx - vq->last_avail) > vq->qsize)
pr_err ("%s: no valid descriptor\n", vq->base->vops->name);
else
ret = true;
}
return ret;
}
/**