В ядре Linux устранена следующая уязвимость:
nvmet-rdma: обрабатывать встроенные данные с ненулевым смещением.
nvmet_rdma_use_inline_sg() отображает смещение встроенных данных, управляемое хостом.
во встроенный список разброса для каждой команды. Проверка границ допускает любые
смещение с помощью off + len <= inline_data_size, но отображение по-прежнему предполагает
данные начинаются с первой встроенной страницы:
sg->смещение = выключено;
sg->length = min_t(int, len, PAGE_SIZE - выкл);
Если для порта настроен параметр inline_data_size > PAGE_SIZE (настраивается
до max(SZ_16K, PAGE_SIZE)), смещение в (PAGE_SIZE, inline_data_size]
приводит к опустошению PAGE_SIZE - off, поэтому для sg->length установлено значение ~ 4 ГиБ и
серверная часть блока считывает далеко за пределы первой встроенной страницы. num_pages(длина)
также игнорирует смещение, поэтому смещение в границах которого [off, off+len)
диапазон пересекает границу страницы, что приводит к занижению списка разброса. Правильно сопоставьте смещение: разделите его на индекс страницы и внутристраничный индекс.
смещение, начните список разброса на этой странице и измените количество страниц с
page_off + лен.
Поскольку список разброса запросов теперь может начинаться с
inline_sg[page_idx] вместо inline_sg[0], обобщите встроенный SGL
проверка идентичности в nvmet_rdma_release_rsp() для проверки диапазона; в противном случае
постоянный встроенный список разброса ошибочно принимается за выделенный и
nvmet_req_free_sgls() освобождает встроенную страницу (и предупреждает в
free_large_kmalloc()).
Показать оригинальное описание (EN)
In the Linux kernel, the following vulnerability has been resolved: nvmet-rdma: handle inline data with a nonzero offset nvmet_rdma_use_inline_sg() maps the host-controlled inline data offset into the per-command inline scatterlist. The bounds check admits any offset with off + len <= inline_data_size, but the mapping still assumes the data begins in the first inline page: sg->offset = off; sg->length = min_t(int, len, PAGE_SIZE - off); When a port is configured with inline_data_size > PAGE_SIZE (settable up to max(SZ_16K, PAGE_SIZE)), an offset in (PAGE_SIZE, inline_data_size] makes "PAGE_SIZE - off" underflow, so sg->length is set to ~4 GiB and the block backend reads far past the first inline page. num_pages(len) also ignores the offset, so an in-bounds offset whose [off, off+len) span crosses a page boundary under-counts the scatterlist. Map the offset properly: split it into a page index and an in-page offset, start the scatterlist at that page, and size the page count from page_off + len. Because the request scatterlist may now start at inline_sg[page_idx] rather than inline_sg[0], generalize the inline-SGL identity test in nvmet_rdma_release_rsp() to a range test; otherwise the persistent inline scatterlist is mistaken for an allocated one and nvmet_req_free_sgls() frees an inline page (and warns in free_large_kmalloc()).
Характеристики атаки
Последствия
Строка CVSS v3.1