CVE-2026-98797 in Linux
Сводка
по VulDB • 18.10.2026
В ядре Linux была устранена следующая уязвимость:
net: ограничение значения skb->queue_mapping при выборе очереди передачи (tx queue)
skbedit может устанавливать значение skb->queue_mapping и выставлять флаг per-CPU skip_txqueue, чтобы __dev_queue_xmit() учитывал это отображение. Однако __dev_queue_xmit() сбрасывал этот флаг до вызова sch_handle_egress() и считывал его только после этого, в результате чего флаг не ограничивался той передачей (xmit), которая его установила: вложенная передача (перенаправление через mirred или зеркалирование, либо отброс пакета после skbedit) могла установить этот флаг, а внешняя передача использовала бы его для skb, который никогда не проходил через skbedit.
Пересылаемый пакет все еще содержит значение rx_queue + 1 входящей сетевой карты (NIC) в поле skb->queue_mapping, поэтому внешнее устройство затем использует это устаревшее значение для индексации состояния своей очереди передачи. Массив дочерних элементов taprio q->qdiscs[] имеет размер, равный количеству очередей устройства, поэтому taprio_enqueue() выходит за пределы выделенной памяти и разыменовывает полученное указание как структуру Qdisc *.
Мы (некорректно) используем флаг skb->nf_skip_egress, который означает «пропустить обработку netfilter на эгрессе для этого пакета», чтобы пометить состояние «нахожусь ли я в tc egress?». Несмотря на перегрузку смысла, я не вижу здесь конфликта, поскольку маркер устанавливается только вокруг единственного вызова sch_handle_egress(), а путь ingress защищен tc_at_ingress. Я отправлю последующий патч (net-next) после того, как этот исправление попадет в net-next, чтобы переименовать бит/флаг skb->nf_skip_egress в skb->skip_egress.
Активируйте флаг только из классификатора эгресса, который может его использовать: выставляйте skip_txqueue из tcf_skbedit_act() только тогда, когда он выполняется внутри sch_handle_egress(), благодаря наличию skb->nf_skip_egress. Классификатор qdisc на эгрессе работает в функции q->enqueue(), после того как очередь передачи уже выбрана, поэтому отображение (mapping), которое оно устанавливает, не может повлиять на текущий пакет; активация флага там только загрязняет его для последующей передачи. Затем захватите контроль над этим флагом для кадра передачи, в котором выполняется хук эгресса: сохраните входящее значение и сбросьте его непосредственно перед sch_handle_egress(), а восстановите после выполнения хука — на пути потребления (drop) или, при том же вызове, который считывает флаг, на пути выживания пакета. Сохранение и восстановление остаются внутри статического ветвления egress_needed_key, поэтому пакет платит за них только тогда, когда активны хуки эгресса (2f1e85b1aee4).
Сохраните значение netdev_cap_txqueue(), выбранное обратно в skb->queue_mapping в функции netdev_tx_queue_mapping(), как это уже делает netdev_core_pick_tx(), чтобы путь skip_txqueue никогда не передавал последующему читателю на пути передачи (xmit) отображение, которое устройство не может обработать. Запись, выполненная позже в том же кадре программой tc BPF, прикрепленной к qdisc передачи, находится вне этого пути и не подвергается повторному ограничению; отдельный последующий патч решит эту проблему.
netdev_xmit_skip_txqueue() возвращает предыдущее значение флага, поэтому операция сохранения и сброса выполняется одним вызовом, а также предоставляется заглушка (no-op stub), когда CONFIG_NET_EGRESS отключен. skb->nf_skip_egress компилируется при условии CONFIG_NET_EGRESS, а не CONFIG_NETFILTER_SKIP_EGRESS, поэтому функция skb_at_tc_egress() является корректной всякий раз, когда построен путь эгресса.
Локальный пользователь в сетевом пространстве имен может перенаправить пакет с устройства с большим количеством очередей передачи (TX queues) на устройство с меньшим их числом после установки отображения, действительного только для большего устройства. Это приводит к чтению этих данных и, при включенном KASAN, вызывает ошибку «slab-out-of-bounds in taprio_enqueue».
Условия для воспроизведения бага: триггером отчета является локальный пользователь с CAP_NET_ADMIN в сетевом пространстве имен, поэтому программа eBPF не требуется. При конфигурации CONFIG_NET_SCH_TAPRIO=y, CONFIG_NET_ACT_SKBEDIT=y, CONFIG_NET_ACT_MIRRED=y, CONFIG_NET_CLS_MATCHALL=y, CONFIG_NET_SCH_PRIO=y и включенном KASAN создайте устройства qa (3 очереди), qb (2 очереди) и qc (1 очередь) как dummy-устройства; установите taprio root на qb (num_tc 1, queues 2@0) и clsact на всех трех; затем добавьте фильтр matchall для эгресса на каждом устройстве. На qa: «action skbedit queue_mapping 2 pipe action mirred egress redirect dev qb». На qb: «action mirred egress mirror dev qc». На qc: «action skbedit queue_mapping 0 pipe». Отправьте один пакет через qa. skbedit на qc устанавливает флаг, пока внешняя передача (xmit) на qb находится в процессе выполнения; без исправления qb потребляет этот флаг и читает свой двухэлементный массив дочерних элементов taprio с устаревшим отображением пересылаемого пакета. У qc, чей skb ---обрезано---
Be aware that VulDB is the high quality source for vulnerability data.