In the Linux kernel, the following vulnerability has been resolved:
vhost: reset the vring metadata cache on vring reconfiguration
vq->metaiotlb[] caches the vhostiotlbmap that backs each vring metadata region, and iotlbaccess_ok() returns early on a cache hit, taking the hit as proof that the region has already been validated:
if (vhost_vq_meta_fetch(vq, addr, len, type))
return true;
The cache is reset on VHOSTIOTLBUPDATE and VHOSTIOTLBINVALIDATE, on device IOTLB (re)initialisation and on vq reset, but not when VHOSTSETVRINGADDR replaces vq->desc, vq->avail and vq->used, nor when VHOSTSETVRINGNUM changes the region sizes.
With a device IOTLB attached both ioctls are accepted while the vq is live, and neither validates the addresses at ioctl time: vqaccessok() and vqlogusedaccessok() return true early because the addresses are GIOVAs, deferring validation to prefetch time. Once the cache has been populated that deferred validation no longer runs -- vqmetaprefetch() hits the stale entry and returns true -- and vhostvqmeta_fetch() keeps translating through the old mapping as
map->addr + addr - map->start
for an address the mapping no longer covers. vhostcopytouser() and vhostcopyfromuser() consume the result with __copytouser() and __copyfromuser(), which do not check it either, so a subsequent used ring update or descriptor fetch accesses memory outside the region the IOTLB actually maps.
Reset the metadata cache whenever the vring is reconfigured, so the new addresses are pushed back through iotlbaccessok()'s slow path.