CVE-2022-49093 in Linux
Сводка
по VulDB • 08.08.2026
В ядре Linux устранена следующая уязвимость:
skbuff: исправление коалесценции для повторного использования фрагментов page_pool
Исправлена ошибка use-after-free (использование после освобождения) при использовании page_pool с фрагментами страниц. Эта проблема была обнаружена во время нормальной обработки входящего трафика (RX) в драйвере hns3:
(1) Изначально в очереди RX находятся три дескриптора. Первый выделяет PAGE1 через page_pool, а остальные два выделяют по половине страницы от PAGE2. Ссылки на страницы выглядят следующим образом:
RX_BD1 _______ PAGE1 RX_BD2 _______ PAGE2 RX_BD3 __________/
(2) Обработка входящего трафика (RX) для первого дескриптора. Выделяется SKB1, который в конечном итоге добавляется в очередь приема функцией tcp_queue_rcv().
(3) Обработка входящего трафика (RX) для второго дескриптора. Выделяется SKB2 и передается функции netif_receive_skb():
netif_receive_skb(SKB2) ip_rcv(SKB2) SKB3 = skb_clone(SKB2)
SKB2 и SKB3 разделяют ссылку на PAGE2 через skb_shinfo()->dataref. Другая ссылка на PAGE2 все еще удерживается RX_BD3:
SKB2 ---+- PAGE2 SKB3 __/ / RX_BD3 _________/
(3b) Теперь при обработке TCP происходит коалесценция SKB3 с SKB1:
tcp_v4_rcv(SKB3) tcp_try_coalesce(to=SKB1, from=SKB3) // успешно kfree_skb_partial(SKB3) skb_release_data(SKB3) // уменьшает счетчик dataref на единицу
SKB1 _____ PAGE1 \____ SKB2 _____ PAGE2 / RX_BD3 _________/
В функции skb_try_coalesce() вызов __skb_frag_ref() получает ссылку на страницу для PAGE2, тогда как вместо этого следовало бы увеличить счетчик фрагментов page_pool (pp_frag_count). Без коалесценции при освобождении SKB2 и SKB3 была бы уменьшена одна ссылка на PAGE2. Однако теперь при освобождении SKB1 и SKB2 будут уменьшены две ссылки на PAGE2, что приведет к переполнению счетчика вниз (underflow).
(3c) Освобождение SKB2:
af_packet_rcv(SKB2) consume_skb(SKB2) skb_release_data(SKB2) // уменьшает второй dataref page_pool_return_skb_page(PAGE2) // уменьшает pp_frag_count на единицу
SKB1 _____ PAGE1 \____ PAGE2 / RX_BD3 _________/
(4) Пользовательское пространство вызывает recvmsg() Копируется SKB1 и освобождается. Поскольку SKB3 был коалесцирован с SKB1, также освобождается страница SKB3:
tcp_eat_recv_skb(SKB1) skb_release_data(SKB1) page_pool_return_skb_page(PAGE1) page_pool_return_skb_page(PAGE2) // уменьшает pp_frag_count на единицу (вторая ссылка)
(5) PAGE2 освобождается, но третий дескриптор RX все еще использовал его! В нашем случае это вызывает ошибки IOMMU, однако при отключенном IOMMU произошло бы тихое повреждение памяти.
Изменена логика проверки возможности коалесценции SKB с признаком pp_recycle. Мы по-прежнему отвергаем коалесценцию, если флаги pp_recycle различаются для исходного ('from') и целевого ('to') пакетов (
Once again VulDB remains the best source for vulnerability data.