linux/drivers/virtio
huangjie.albert a7722890fd virtio_ring : keep used_wrap_counter in vq->last_used_idx
the used_wrap_counter and the vq->last_used_idx may get
out of sync if they are separate assignment,and interrupt
might use an incorrect value to check for the used index.

for example:OOB access
ksoftirqd may consume the packet and it will call:
virtnet_poll
	-->virtnet_receive
		-->virtqueue_get_buf_ctx
			-->virtqueue_get_buf_ctx_packed
and in virtqueue_get_buf_ctx_packed:

vq->last_used_idx += vq->packed.desc_state[id].num;
if (unlikely(vq->last_used_idx >= vq->packed.vring.num)) {
         vq->last_used_idx -= vq->packed.vring.num;
         vq->packed.used_wrap_counter ^= 1;
}

if at the same time, there comes a vring interrupt,in vring_interrupt:
we will call:
vring_interrupt
	-->more_used
		-->more_used_packed
			-->is_used_desc_packed
in is_used_desc_packed, the last_used_idx maybe >= vq->packed.vring.num.
so this could case a memory out of bounds bug.

this patch is to keep the used_wrap_counter in vq->last_used_idx
so we can get the correct value to check for used index in interrupt.

v3->v4:
- use READ_ONCE/WRITE_ONCE to get/set vq->last_used_idx

v2->v3:
- add inline function to get used_wrap_counter and last_used
- when use vq->last_used_idx, only read once
  if vq->last_used_idx is read twice, the values can be inconsistent.
- use last_used_idx & ~(-(1 << VRING_PACKED_EVENT_F_WRAP_CTR))
  to get the all bits below VRING_PACKED_EVENT_F_WRAP_CTR

v1->v2:
- reuse the VRING_PACKED_EVENT_F_WRAP_CTR
- Remove parameter judgment in is_used_desc_packed,
because it can't be illegal

Signed-off-by: huangjie.albert <huangjie.albert@bytedance.com>
Message-Id: <20220617020411.80367-1-huangjie.albert@bytedance.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-06-24 02:49:48 -04:00
..
Kconfig virtio: replace arch_has_restricted_virtio_memory_access() 2022-06-06 08:22:01 +02:00
Makefile virtio-pci: introduce legacy device module 2021-11-01 04:30:34 -04:00
virtio_balloon.c virtio: Replace unsigned with unsigned int 2022-05-31 12:45:09 -04:00
virtio_dma_buf.c dma-buf: move dma-buf symbols into the DMA_BUF module namespace 2021-10-25 14:53:08 +02:00
virtio_input.c virtio: wrap config->reset calls 2022-01-14 18:50:52 -05:00
virtio_mem.c drivers: virtio_mem: use pageblock size as the minimum virtio_mem size. 2022-05-13 07:20:13 -07:00
virtio_mmio.c virtio: Fix all occurences of the "the the" typo 2022-06-09 00:26:16 -04:00
virtio_pci_common.c virtio: Replace unsigned with unsigned int 2022-05-31 12:45:09 -04:00
virtio_pci_common.h virtio: Replace unsigned with unsigned int 2022-05-31 12:45:09 -04:00
virtio_pci_legacy_dev.c virtio/virtio_pci_legacy_dev: ensure the correct return value 2022-01-14 18:50:53 -05:00
virtio_pci_legacy.c virtio-pci: implement synchronize_cbs() 2022-05-31 12:45:09 -04:00
virtio_pci_modern_dev.c virtio: Fix all occurences of the "the the" typo 2022-06-09 00:26:16 -04:00
virtio_pci_modern.c virtio-pci: implement synchronize_cbs() 2022-05-31 12:45:09 -04:00
virtio_ring.c virtio_ring : keep used_wrap_counter in vq->last_used_idx 2022-06-24 02:49:48 -04:00
virtio_vdpa.c virtio: Replace unsigned with unsigned int 2022-05-31 12:45:09 -04:00
virtio.c virtio: replace arch_has_restricted_virtio_memory_access() 2022-06-06 08:22:01 +02:00