Ad

CVE-2026-72112

HIGH CVSS 3.1: 7,8 EPSS 0.15%
Обновлено 17 августа 2026
Linux
Параметр Значение
CVSS 7,8 (HIGH)
Поставщик Linux
Публичный эксплойт Нет

В ядре Linux устранена следующая уязвимость: io_uring/bpf-ops: отклонить перерегистрацию уже связанного оператора. io_install_bpf() отклоняет только вторую регистрацию на стороне ctx (ctx->bpf_ops) и устанавливает обратный указатель для каждой карты ops->priv безоговорочно. Путь ссылки struct_ops никогда не перемещается дальше карты. BPF_STRUCT_OPS_STATE_READY, поэтому та же самая карта io_uring_bpf_ops может быть зарегистрировано более одного раза, и bpf_io_reg() повторно разрешает целевое кольцо через fget(ops->ring_fd) при каждом вызове. Таким образом, вызывающий абонент может указать тот же Ring_fd в другом io_ring_ctx между двумя BPF_LINK_CREATE звонки.

Вторая регистрация проходит проверку ctx->bpf_ops (новый ctx имеет none) и перезаписывает ops->priv, делая потерянным первый ctx. Разборка (io_eject_bpf()/bpf_io_unreg()) достигает ctx только через ops->priv, поэтому потерянный ctx никогда не удаляется: его ctx->loop_step продолжает указывать в батут struct_ops, который освобождается, как только карта исчезает. А позже io_uring_enter() на потерянном кольце затем вызывает висячий ctx->loop_step из io_run_loop() — использование после освобождения освобожденного исполняемая память, доступная задаче с CAP_BPF + CAP_PERFMON.

Отклонить регистрацию, если ops->priv уже установлен, как hid_bpf_reg() делает для своего struct_ops.

Показать оригинальное описание (EN)

In the Linux kernel, the following vulnerability has been resolved: io_uring/bpf-ops: reject re-registration of an already-bound ops io_install_bpf() only rejects a second registration on the ctx side (ctx->bpf_ops) and sets the per-map back-pointer ops->priv unconditionally. The struct_ops link path never advances a map past BPF_STRUCT_OPS_STATE_READY, so the same io_uring_bpf_ops map can be registered more than once, and bpf_io_reg() re-resolves the target ring via fget(ops->ring_fd) on every call. A caller can therefore point the same ring_fd at a different io_ring_ctx between two BPF_LINK_CREATE calls. The second registration passes the ctx->bpf_ops check (the new ctx has none) and overwrites ops->priv, orphaning the first ctx. Teardown (io_eject_bpf()/bpf_io_unreg()) only reaches a ctx through ops->priv, so the orphaned ctx is never torn down: its ctx->loop_step keeps pointing into the struct_ops trampoline, which is freed once the map is gone. A later io_uring_enter() on the orphaned ring then calls the dangling ctx->loop_step from io_run_loop() -- a use-after-free of freed executable memory, reachable by a task with CAP_BPF + CAP_PERFMON. Reject registration when ops->priv is already set, as hid_bpf_reg() does for its struct_ops.

Характеристики атаки

Способ атаки
Локальный
Нужен локальный доступ
Сложность
Низкая
Легко эксплуатировать
Нужны права
Низкие
Нужны базовые права
Участие пользователя
Не требуется
Не нужно действие пользователя

Последствия

Конфиденциальность
Высокое
Полная утечка данных
Целостность
Высокое
Полная модификация данных
Доступность
Высокое
Полный отказ в обслуживании

Строка CVSS v3.1