Package: openvpn-dco-dkms
Version: 0.0+git20241121-1
Severity: important
Tags: upstream fixed-upstream
X-Debbugs-Cc:
Dear Maintainer,
The ovpn_dco_v2 module built from the snapshot in trixie/stable
(0.0+git20241121-1) contains a use-after-free in the peer-deletion path
that causes a kernel NULL-pointer dereference under high client
connect/disconnect concurrency. It is fixed upstream (commit f74c59a7,
2026-05-14) but the fix is not present in any released Debian version.
== The defect ==
In drivers/net/ovpn-dco/peer.c, ovpn_peer_delete_work() releases the peer
*before* using it:
static void ovpn_peer_delete_work(struct work_struct *work)
{
struct ovpn_peer *peer = container_of(work, struct ovpn_peer,
delete_work);
ovpn_peer_release(peer); /* arms call_rcu() ->
frees peer */
ovpn_netlink_notify_del_peer(peer); /* then derefs
peer->ovpn->dev */
}
ovpn_peer_release() ends in call_rcu(&peer->rcu, ovpn_peer_release_rcu),
whose callback (ovpn_peer_release_rcu -> ovpn_peer_free) does
dev_put(peer->ovpn->dev) and kfree(peer). Because ovpn_peer_delete_work()
is not in an RCU read-side critical section, that callback can run (on any
CPU) before ovpn_netlink_notify_del_peer() executes. That function then
dereferences peer->ovpn->dev (netdev_info(), nla_put_u32(... ifindex ...),
genlmsg_multicast_netns(dev_net(...))) through freed memory.
In steady state the RCU grace period is long relative to the function, so
the free happens later and nothing is observed. Under a mass simultaneous
reconnect (hundreds of peers deleted/recreated at once on a multi-core
host), grace periods complete in milliseconds and the free races ahead of
the notification -> NULL-pointer dereference.
== Observed crash ==
BUG: kernel NULL pointer dereference, address: 0000000000000000
RIP: ovpn_netlink_notify_del_peer+0xa8 [ovpn_dco_v2]
Workqueue: ovpn-event-wq-<dev> ovpn_peer_delete_work [ovpn_dco_v2]
CR2: 0000000000000000 RAX: 0000000000000000
After the first oops the module's peer table is corrupted: subsequent peer
deletions oops repeatedly, the tun interface loses its address, and the
module reaches a state where rmmod -f fails ("Device or resource busy",
refcount underflow). A full reboot does not help if clients immediately
reconnect (the oops loop resumes within minutes); the only recovery is to
disable DCO (disable-dco in the OpenVPN server config) so peer operations
go through userspace instead of the kernel module.
== Environment ==
Debian 13 (trixie), kernel 6.12.x-cloud-amd64
openvpn 2.6.14-1+deb13u2
openvpn-dco-dkms 0.0+git20241121-1
Multi-vCPU host, OpenVPN UDP server with several hundred clients;
triggered by a mass simultaneous client reconnect.
== Fix ==
Fixed upstream in OpenVPN/ovpn-dco by commit f74c59a7
("ovpn-dco: avoid UAF when releasing peer", 2026-05-14):
https://github.com/OpenVPN/ovpn-dco/commit/f74c59a7e2c8b63958f556df74a585d54e2ac660
which simply reorders the two calls so the notification runs while the peer
is still valid:
ovpn_netlink_notify_del_peer(peer); /* notify first */
ovpn_peer_release(peer); /* then schedule the free */
A companion commit addresses a related NAPI add/delete race
("ovpn-dco: serialize peer NAPI add/delete", 2026-05-14):
https://github.com/OpenVPN/ovpn-dco/commit/ef379eae8534a7bc4847d8545573b00c5f4887ae
Neither is in any released Debian version: trixie/stable ships
0.0+git20241121-1 and testing/unstable ship 0.0+git20251017-1, both of
which predate the May-2026 fix.
== Request ==
Please update openvpn-dco-dkms to an upstream snapshot that includes
f74c59a7 (and ideally ef379eae). The primary fix is a two-line reorder and
is trivially cherry-pickable as a patch if a full snapshot bump is not
desired for stable.
Note: OpenVPN/ovpn-dco is upstream in bugfix-only/maintenance mode (it
supports OpenVPN 2.6.x). For OpenVPN 2.7+ the replacement is the in-tree
"ovpn" module (Linux 6.16+) / the OpenVPN/ovpn-backports project; this
report concerns the 2.6.x ovpn-dco module shipped in trixie.
Thank you.
Thomas