CVE-2026-64045

In the Linux kernel, the following vulnerability has been resolved: ovpn: tcp - use cached peer pointer in ovpn_tcp_close() ovpn_tcp_close() loads the ovpn_socket via rcu_dereference_sk_user_data() under rcu_read_lock(), takes a reference on sock->peer, caches the peer pointer in a local, and drops the read lock. It then passes sock->peer (rather than the cached local) to ovpn_peer_del(), re-dereferencing the ovpn_socket after the RCU read section has ended. Unlike ovpn_tcp_sendmsg(), which uses the same "load under RCU, use after unlock" pattern but is protected by lock_sock() held across the function, ovpn_tcp_close() runs without the socket lock: inet_release() invokes sk_prot->close() without taking lock_sock first. ovpn_socket_release() can therefore complete its kref_put -> detach -> synchronize_rcu -> kfree(sock) sequence concurrently, in the window after ovpn_tcp_close() drops rcu_read_lock() but before it dereferences sock->peer. The synchronize_rcu() in ovpn_socket_release() protects readers that use the dereferenced pointer inside the RCU read section, not those that escape the pointer to a local and use it afterwards. A reproducer follows the pattern of commit 94560267d6c4 ("ovpn: tcp - don't deref NULL sk_socket member after tcp_close()"): trigger a peer removal (keepalive expiration or netlink OVPN_CMD_DEL_PEER) at the same moment userspace closes the TCP fd. That commit fixed the detach-side of the same race window; this one fixes the close-side at a different victim. Tighten the entry block to read sock->peer exactly once into the cached peer local, and route all subsequent uses (the hold check, the ovpn_peer_del() call, and the prot->close() invocation) through that local. sock->peer is only ever written once in ovpn_socket_new() under lock_sock(), before rcu_assign_sk_user_data() publishes the ovpn_socket, and is never reassigned afterwards - but the previous multi-read pattern made that invariant implicit rather than explicit. The same multi-read shape exists in ovpn_tcp_recvmsg(), ovpn_tcp_sendmsg(), ovpn_tcp_data_ready() and ovpn_tcp_write_space(); those will be cleaned up via a dedicated helper in a follow-up net-next series.
Configurations

Configuration 1 (hide)

OR cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.1:rc4:*:*:*:*:*:*

History

24 Oct 2026, 20:10

Type Values Removed Values Added
Summary
  • (es) En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta: ovpn: tcp - usar puntero de par en caché en ovpn_tcp_close() ovpn_tcp_close() carga el ovpn_socket a través de rcu_dereference_sk_user_data() bajo rcu_read_lock(), toma una referencia en sock -> peer, almacena en caché el puntero del par en una variable local, y libera el bloqueo de lectura. Luego pasa sock -> peer (en lugar de la variable local en caché) a ovpn_peer_del(), volviendo a desreferenciar el ovpn_socket después de que la sección de lectura RCU haya terminado. A diferencia de ovpn_tcp_sendmsg(), que utiliza el mismo patrón de ’cargar bajo RCU, usar después de desbloquear’ pero está protegido por lock_sock() mantenido durante toda la función, ovpn_tcp_close() se ejecuta sin el bloqueo del socket: inet_release() invoca sk_prot -> close() sin tomar lock_sock primero. Por lo tanto, ovpn_socket_release() puede completar su secuencia kref_put -> detach -> synchronize_rcu -> kfree(sock) concurrentemente, en la ventana después de que ovpn_tcp_close() libera rcu_read_lock() pero antes de que desreferencie sock -> peer. El synchronize_rcu() en ovpn_socket_release() protege a los lectores que usan el puntero desreferenciado dentro de la sección de lectura RCU, no a aquellos que escapan el puntero a una variable local y lo usan después. Un reproductor sigue el patrón del commit 94560267d6c4 (’ovpn: tcp - no desreferenciar miembro sk_socket NULL después de tcp_close()’): activar una eliminación de par (expiración de keepalive o netlink OVPN_CMD_DEL_PEER) en el mismo momento en que el espacio de usuario cierra el descriptor de archivo TCP. Ese commit corrigió el lado de desvinculación de la misma ventana de carrera; este corrige el lado de cierre en una víctima diferente. Ajustar el bloque de entrada para leer sock -> peer exactamente una vez en la variable local del par en caché, y enrutar todos los usos subsiguientes (la verificación de retención, la llamada a ovpn_peer_del() y la invocación de prot -> close()) a través de esa variable local. sock -> peer solo se escribe una vez en ovpn_socket_new() bajo lock_sock(), antes de que rcu_assign_sk_user_data() publique el ovpn_socket, y nunca se reasigna después, pero el patrón de múltiples lecturas anterior hizo que ese invariante fuera implícito en lugar de explícito. La misma forma de múltiples lecturas existe en ovpn_tcp_recvmsg(), ovpn_tcp_sendmsg(), ovpn_tcp_data_ready() y ovpn_tcp_write_space(); estos se limpiarán mediante una función auxiliar dedicada en una serie net-next de seguimiento.

Information

Published : 2026-07-19 16:17

Updated : 2026-10-24 20:10


NVD link : CVE-2026-64045

Mitre link : CVE-2026-64045

CVE.ORG link : CVE-2026-64045


JSON object : View

Products Affected

linux

  • linux_kernel
CWE
CWE-476

NULL Pointer Dereference