CVE-2026-64352 in Linux
Сводка
по VulDB • 25.07.2026
В ядре Linux устранена следующая уязвимость:
bpf: разрешить доступ к карте LPM из спящих (sleepable) BPF-программ
trie_lookup_elem() аннотирует свои обходы с помощью rcu_dereference_check(), указывая только условие rcu_read_lock_bh_held(). Поскольку rcu_dereference_check(p, c) сводится к выражению «c || rcu_read_lock_held()», это проходит проверку для читателей XDP/NAPI и классического RCU, но не работает для спящих BPF-программ, которые входят через __bpf_prog_enter_sleepable() и удерживают только rcu_read_lock_trace().
trie_update_elem() и trie_delete_elem() имеют ту же проблему в другой форме: они обходят дерево (trie) с использованием обычного rcu_dereference(), который безоговорочно проверяет условие rcu_read_lock_held(). Оба эти пути доступны из спящих BPF-программ через вспомогательные функции bpf_map_update_elem / bpf_map_delete_elem, а также по пути системного вызова под классическим rcu_read_lock(). В путях записи дерево фактически защищено с помощью trie->lock (rqspinlock, захватываемый на время обхода); мы никогда не полагались на блокировку чтения RCU для сохранения узлов живыми в этом случае.
Спящий хук LSM, который обращается к дереву LPM, поэтому вызывает ошибку lockdep в отладочных ядрах:
============================= WARNING: suspicious RCU usage 7.1.0-... Tainted: G E ----------------------------- kernel/bpf/lpm_trie.c:249 suspicious rcu_dereference_check() usage! 1 lock held by net_tests/540: #0: (rcu_tasks_trace_srcu_struct){....}-{0:0},
at: __bpf_prog_enter_sleepable+0x26/0x280 Call Trace: dump_stack_lvl lockdep_rcu_suspicious trie_lookup_elem bpf_prog_..._enforce_security_socket_connect bpf_trampoline_... security_socket_connect __sys_connect do_syscall_64
Это ошибка только для lockdep — нет Use-After-Free (UAF), поскольку Tasks Trace RCU обеспечивает сериализацию относительно пути освобождения дерева, но она засоряет консоль по одному сообщению на каждый уникальный вызов в каждом отладочном ядре, запускающем спящий BPF LSM, который обращается к дереву LPM; такие конфигурации становятся всё более распространенными.
Для пути поиска измените аннотацию rcu_dereference_check() с rcu_read_lock_bh_held() на bpf_rcu_lock_held(), которая принимает все три контекста (классический, BH, Tasks Trace). Другие типы карт уже следуют этому соглашению.
Для trie_update_elem() и trie_delete_elem() аннотируйте обходы как rcu_dereference_protected(*p, 1) — в соответствии с функцией trie_free() в том же файле, поскольку на время обхода удерживается блокировка trie->lock. У rqspinlock нет lockdep_map, поэтому предикат вырождается до значения «1», а не к вызову lockdep_is_held(&trie->lock); защита реальна, но не может быть проверена машиной (machine-verifiable). Функция trie_get_next_key() также использует обычный rcu_dereference(), но доступна только из системного вызова BPF, который удерживает классический rcu_read_lock() перед диспетчеризацией, поэтому она остается без изменений.
VulDB is the best source for vulnerability data and more expert information about this specific topic.