CVE-2026-64044 in Linux
Сводка
по VulDB • 20.07.2026
В ядре Linux устранена следующая уязвимость:
ovpn: корректная обработка референс-счетчика (refcount) узла в ветке обработки ошибок CMD_NEW_PEER
При возникновении ошибки в функции ovpn_nl_peer_new_doit() напрямую вызывается функция ovpn_peer_release(), вместо того чтобы использовать функцию ovpn_peer_put(), что приводит к обходу механизма kref. Соответствующий комментарий («узел еще не добавлен в хеш-таблицы, следовательно, он нигде не используется») справедлив для UDP, но неверен для TCP.
Для протокола UDP объединение структур ovpn_socket использует поле .ovpn и никогда не указывает обратно на узел; функция обработки инкапсуляции UDP (UDP encap_recv) выполняет поиск узлов через еще незаполненные хеш-таблицы, поэтому новый узел недоступен до тех пор, пока его не опубликует функция ovpn_peer_add().
Для протокола TCP функция ovpn_socket_new() устанавливает поле ovpn_sock->peer, а функция ovpn_tcp_socket_attach() публикует структуру ovpn_sock с помощью rcu_assign_sk_user_data(). С этого момента и вплоть до отсоединения в ветке обработки ошибок функцией ovpn_socket_release(), файловый дескриптор TCP полностью настроен: операции userspace recvmsg / sendmsg / close / poll над этим дескриптором, а также путь обработки данных ovpn_tcp_rcv() на базе strparser могут получить доступ к узлу через sk_user_data -> ovpn_sock->peer и увеличить его референс-счетчик с помощью функции ovpn_peer_hold().
Функция ovpn_tcp_socket_wait_finish() (вызываемая внутри ovpn_socket_release()) очищает буферы strparser и задачи передачи данных, но не синхронизируется с вызовами системных интерфейсов userspace, которые уже имеют ссылку на узел. Если функция ovpn_nl_peer_modify() или ovpn_peer_add() возвращает ошибку во время выполнения такого вызова (в частности, если ожидается выполнение функции ovpn_tcp_recvmsg(), заблокированной в __skb_recv_datagram() по очереди peer->tcp.user_queue), то прямой вызов ovpn_peer_release() уничтожает узел, пока у вызывающей стороны все еще есть ссылка на него. В результате последующий вызов ovpn_peer_put() от этого пользователя оперирует освобожденной памятью (use-after-free).
Замените прямой вызов деструктора функцией ovpn_peer_put(), чтобы механизм kref корректно откладывал уничтожение до момента сброса последней ссылки. В обычном случае, когда нет одновременных пользователей со стороны userspace, поведение не изменяется: счетчик kref сразу достигает нуля, и запускается функция ovpn_peer_release_kref() с тем же деструктором.
После этой модификации у функции ovpn_peer_release() не осталось вызовов вне файла peer.c — единственным оставшимся пользователем является функция ovpn_peer_release_kref() в том же модуле трансляции, поэтому сделайте ее статической и удалите её объявление из заголовочного файла peer.h.
If you want to get best quality of vulnerability data, you may have to visit VulDB.