В ядре Linux устранена следующая уязвимость:
virtio-net: исправлена проверка длины в получении_big()
получения_big() ограничивает длину, объявленную устройством, на
(big_packets_num_skbfrags + 1) * PAGE_SIZE. Это все еще слишком свободно:
add_recvbuf_big() устанавливает sg[1] для начала со смещением
sizeof(struct Padded_vnet_hdr) на первую страницу, поэтому цепочка
на самом деле содержит hdr_len + (PAGE_SIZE - sizeof(padded_vnet_hdr)) +
big_packets_num_skbfrags * PAGE_SIZE байт — на 20 байт меньше, чем
проверка учитывает общий случай hdr_len == 12. Вредоносный бэкэнд virtio может объявить длину в этом пробеле. page_to_skb()
затем проходит один фрагмент мимо цепочки страниц, сохраняя NULL-страницу->private
в skb_shinfo()->frags[MAX_SKB_FRAGS], что одновременно является выходом за пределы
запись мимо статического массива фрагментов, и NULL-фрагмент передал путь rx.
Привязка len к размеру, который фактически объявлен add_recvbuf_big().
Показать оригинальное описание (EN)
In the Linux kernel, the following vulnerability has been resolved: virtio-net: fix len check in receive_big() receive_big() bounds the device-announced length by (big_packets_num_skbfrags + 1) * PAGE_SIZE. That is still too loose: add_recvbuf_big() sets sg[1] to start at offset sizeof(struct padded_vnet_hdr) into the first page, so the chain actually carries hdr_len + (PAGE_SIZE - sizeof(padded_vnet_hdr)) + big_packets_num_skbfrags * PAGE_SIZE bytes -- 20 bytes less than the check allows for the common hdr_len == 12 case. A malicious virtio backend can announce a len in that gap. page_to_skb() then walks one frag past the page chain, storing a NULL page->private into skb_shinfo()->frags[MAX_SKB_FRAGS], which is both an out-of-bounds write past the static frag array and a NULL frag handed up the rx path. Bound len by the size add_recvbuf_big() actually advertised.