virtio: add virtio callbacks check

CVE# CVE-2021-23904
We can only call these callbacks when they are not NULL.

Tracked-On: #5342

Signed-off-by: Jie Deng <jie.deng@intel.com>
Signed-off-by: Yonghua Huang<yonghua.huang@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
Yonghua Huang 2021-07-02 11:53:28 +08:00 committed by wenlingz
parent d74f25fde4
commit e09ecb13eb

View File

@ -760,7 +760,7 @@ virtio_pci_legacy_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
const char *name; const char *name;
uint32_t newoff; uint32_t newoff;
uint32_t value; uint32_t value;
int error; int error = -1;
/* XXX probably should do something better than just assert() */ /* XXX probably should do something better than just assert() */
assert(baridx == base->legacy_pio_bar_idx); assert(baridx == base->legacy_pio_bar_idx);
@ -790,8 +790,11 @@ virtio_pci_legacy_read(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
max = vops->cfgsize ? vops->cfgsize : 0x100000000; max = vops->cfgsize ? vops->cfgsize : 0x100000000;
if (newoff + size > max) if (newoff + size > max)
goto bad; goto bad;
error = (*vops->cfgread)(DEV_STRUCT(base), newoff,
size, &value); if (vops->cfgread) {
error = (*vops->cfgread)(DEV_STRUCT(base), newoff,
size, &value);
}
if (!error) if (!error)
goto done; goto done;
} }
@ -874,7 +877,7 @@ virtio_pci_legacy_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
uint64_t virtio_config_size, max; uint64_t virtio_config_size, max;
const char *name; const char *name;
uint32_t newoff; uint32_t newoff;
int error; int error = -1;
/* XXX probably should do something better than just assert() */ /* XXX probably should do something better than just assert() */
assert(baridx == base->legacy_pio_bar_idx); assert(baridx == base->legacy_pio_bar_idx);
@ -902,8 +905,10 @@ virtio_pci_legacy_write(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
max = vops->cfgsize ? vops->cfgsize : 0x100000000; max = vops->cfgsize ? vops->cfgsize : 0x100000000;
if (newoff + size > max) if (newoff + size > max)
goto bad; goto bad;
error = (*vops->cfgwrite)(DEV_STRUCT(base), newoff, if (vops->cfgwrite) {
size, value); error = (*vops->cfgwrite)(DEV_STRUCT(base), newoff,
size, value);
}
if (!error) if (!error)
goto done; goto done;
} }
@ -969,7 +974,7 @@ bad:
base->status = value; base->status = value;
if (vops->set_status) if (vops->set_status)
(*vops->set_status)(DEV_STRUCT(base), value); (*vops->set_status)(DEV_STRUCT(base), value);
if (value == 0) if ((value == 0) && (vops->reset))
(*vops->reset)(DEV_STRUCT(base)); (*vops->reset)(DEV_STRUCT(base));
if ((value & VIRTIO_CONFIG_S_DRIVER_OK) && if ((value & VIRTIO_CONFIG_S_DRIVER_OK) &&
base->backend_type == BACKEND_VBSU && base->backend_type == BACKEND_VBSU &&
@ -1405,7 +1410,7 @@ virtio_common_cfg_write(struct pci_vdev *dev, uint64_t offset, int size,
base->status = value & 0xff; base->status = value & 0xff;
if (vops->set_status) if (vops->set_status)
(*vops->set_status)(DEV_STRUCT(base), value); (*vops->set_status)(DEV_STRUCT(base), value);
if (base->status == 0) if ((base->status == 0) && (vops->reset))
(*vops->reset)(DEV_STRUCT(base)); (*vops->reset)(DEV_STRUCT(base));
/* TODO: virtio poll mode for modern devices */ /* TODO: virtio poll mode for modern devices */
break; break;
@ -1503,7 +1508,7 @@ virtio_device_cfg_read(struct pci_vdev *dev, uint64_t offset, int size)
const char *name; const char *name;
uint32_t value; uint32_t value;
uint64_t max; uint64_t max;
int error; int error = -1;
vops = base->vops; vops = base->vops;
name = vops->name; name = vops->name;
@ -1517,7 +1522,9 @@ virtio_device_cfg_read(struct pci_vdev *dev, uint64_t offset, int size)
return value; return value;
} }
error = (*vops->cfgread)(DEV_STRUCT(base), offset, size, &value); if (vops->cfgread) {
error = (*vops->cfgread)(DEV_STRUCT(base), offset, size, &value);
}
if (error) { if (error) {
fprintf(stderr, fprintf(stderr,
"%s: reading from 0x%lx size %d failed %d\r\n", "%s: reading from 0x%lx size %d failed %d\r\n",
@ -1536,7 +1543,7 @@ virtio_device_cfg_write(struct pci_vdev *dev, uint64_t offset, int size,
struct virtio_ops *vops; struct virtio_ops *vops;
const char *name; const char *name;
uint64_t max; uint64_t max;
int error; int error = -1;
vops = base->vops; vops = base->vops;
name = vops->name; name = vops->name;
@ -1549,7 +1556,9 @@ virtio_device_cfg_write(struct pci_vdev *dev, uint64_t offset, int size,
return; return;
} }
error = (*vops->cfgwrite)(DEV_STRUCT(base), offset, size, value); if (vops->cfgwrite) {
error = (*vops->cfgwrite)(DEV_STRUCT(base), offset, size, value);
}
if (error) if (error)
fprintf(stderr, fprintf(stderr,
"%s: writing ot 0x%lx size %d failed %d\r\n", "%s: writing ot 0x%lx size %d failed %d\r\n",