Package: release.debian.org Severity: normal Tags: trixie X-Debbugs-Cc: [email protected] Control: affects -1 + src:openvpn-dco-dkms User: [email protected] Usertags: pu
[ Reason ] The OpenVPN DCO kernel offloading module has a race condition that triggers during a peer deletion storm (i.e. when a highly loaded VPN server suffers from a connectivity problem). It causes a NULL pointer dereference. It is reported as https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1140548 This problem has been fixed in a newer upstream release, this update cherry-picks two upstream commits. [ Impact ] NULL pointer dereference on heavily used OpenVPN 2.6 servers running trixie. [ Tests ] Upstream is running extensive peer-review on patches and testsuites. Additionally the reporter has confirmed the proposed package to fix this problem. [ Risks ] Clean backport of two released upstream commits. [ Checklist ] [X] *all* changes are documented in the d/changelog [X] I reviewed all changes and I approve them [X] attach debdiff against the package in (old)stable [/] the issue is verified as fixed in unstable [ Changes ] see above [ Other info ] Heavy disconnect/reconnect storms cause issues on both kernel and userspace side. This -pu fixes the kernel side not to lock up, which is the more annoying problem (you cannot rmmod when it happens, you need to reboot). The userspace side is tracked in #1140745. This is harder to fix in a stable update, because you either need to backport several other changes before or use the patch provided by the reporter, which is not based on released upstream changes. Or we update to a new upstream version in stable. However, problem in userspace is easier to recover from. I will look at that later. Note that while technically this bug has been fixed in unstable by uploading a new upstream version, openvpn-dco-dkms is not really relevant there (OpenVPN 2.7 uses the in-tree ovpn-dco module)
diff -Nru openvpn-dco-dkms-0.0+git20241121/debian/changelog openvpn-dco-dkms-0.0+git20241121/debian/changelog --- openvpn-dco-dkms-0.0+git20241121/debian/changelog 2024-12-08 14:37:32.000000000 +0100 +++ openvpn-dco-dkms-0.0+git20241121/debian/changelog 2026-06-23 23:58:52.000000000 +0200 @@ -1,3 +1,11 @@ +openvpn-dco-dkms (0.0+git20241121-1+deb13u1) trixie; urgency=medium + + * Add debian/gbp.conf for debian/trixie branch + * Cherry-Pick upstream patches to fix NULL deref in ovpn_netlink_notify_del_peer + (Closes: #1140548) + + -- Bernhard Schmidt <[email protected]> Tue, 23 Jun 2026 23:58:52 +0200 + openvpn-dco-dkms (0.0+git20241121-1) unstable; urgency=medium * New upstream version 0.0+git20241121 diff -Nru openvpn-dco-dkms-0.0+git20241121/debian/gbp.conf openvpn-dco-dkms-0.0+git20241121/debian/gbp.conf --- openvpn-dco-dkms-0.0+git20241121/debian/gbp.conf 1970-01-01 01:00:00.000000000 +0100 +++ openvpn-dco-dkms-0.0+git20241121/debian/gbp.conf 2026-06-23 23:58:52.000000000 +0200 @@ -0,0 +1,3 @@ +[DEFAULT] +debian-branch = debian/trixie + diff -Nru openvpn-dco-dkms-0.0+git20241121/debian/patches/avoid-UAF-when-releasing-peer.patch openvpn-dco-dkms-0.0+git20241121/debian/patches/avoid-UAF-when-releasing-peer.patch --- openvpn-dco-dkms-0.0+git20241121/debian/patches/avoid-UAF-when-releasing-peer.patch 1970-01-01 01:00:00.000000000 +0100 +++ openvpn-dco-dkms-0.0+git20241121/debian/patches/avoid-UAF-when-releasing-peer.patch 2026-06-23 23:58:52.000000000 +0200 @@ -0,0 +1,35 @@ +From f74c59a7e2c8b63958f556df74a585d54e2ac660 Mon Sep 17 00:00:00 2001 +From: Antonio Quartulli <[email protected]> +Date: Thu, 14 May 2026 11:56:21 +0200 +Subject: [PATCH] ovpn-dco: avoid UAF when releasing peer + +ovpn_peer_release() schedules a RCU callback which actually +frees the peer object. + +Since we are not in an RCU read critical section, the callback +may get scheduled any time, therefore the peer should not be +accessed after having invoked ovpn_peer_release(). + +Move the call to ovpn_netlink_notify_del_peer() after the +invokation of ovpn_peer_release() and avoid a use-after-free. + +Reported-by: Ralf Lici <[email protected]> +Signed-off-by: Antonio Quartulli <[email protected]> +--- + drivers/net/ovpn-dco/peer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ovpn-dco/peer.c b/drivers/net/ovpn-dco/peer.c +index 4a5d41e..167fa62 100644 +--- a/drivers/net/ovpn-dco/peer.c ++++ b/drivers/net/ovpn-dco/peer.c +@@ -237,8 +237,8 @@ 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); + ovpn_netlink_notify_del_peer(peer); ++ ovpn_peer_release(peer); + } + + /* Use with kref_put calls, when releasing refcount diff -Nru openvpn-dco-dkms-0.0+git20241121/debian/patches/serialize-peer-NAPI-add-delete.patch openvpn-dco-dkms-0.0+git20241121/debian/patches/serialize-peer-NAPI-add-delete.patch --- openvpn-dco-dkms-0.0+git20241121/debian/patches/serialize-peer-NAPI-add-delete.patch 1970-01-01 01:00:00.000000000 +0100 +++ openvpn-dco-dkms-0.0+git20241121/debian/patches/serialize-peer-NAPI-add-delete.patch 2026-06-23 23:58:52.000000000 +0200 @@ -0,0 +1,109 @@ +From ef379eae8534a7bc4847d8545573b00c5f4887ae Mon Sep 17 00:00:00 2001 +From: Ralf Lici <[email protected]> +Date: Thu, 14 May 2026 12:45:17 +0200 +Subject: [PATCH] ovpn-dco: serialize peer NAPI add/delete + +ovpn-dco creates one NAPI instance per peer and registers it against the +ovpn netdev when the peer is created. The NAPI instance is later removed +when the peer is released. + +On older kernels, netif_napi_add* and netif_napi_del do not serialize +updates to the netdev napi_list internally. Peer creation happens from +the netlink path, while peer release may happen asynchronously from the +event workqueue, therefore concurrent peer add/delete can corrupt the +shared netdev NAPI list. + +Serialize the per-peer NAPI registration and unregistration with a mutex +in the ovpn instance. + +Signed-off-by: Ralf Lici <[email protected]> +Signed-off-by: Antonio Quartulli <[email protected]> +--- + drivers/net/ovpn-dco/ovpn.c | 1 + + drivers/net/ovpn-dco/ovpnstruct.h | 4 ++++ + drivers/net/ovpn-dco/peer.c | 24 +++++++++++++++++++----- + 3 files changed, 24 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ovpn-dco/ovpn.c b/drivers/net/ovpn-dco/ovpn.c +index 82e9f94..0961c59 100644 +--- a/drivers/net/ovpn-dco/ovpn.c ++++ b/drivers/net/ovpn-dco/ovpn.c +@@ -66,6 +66,7 @@ int ovpn_struct_init(struct net_device *dev) + + spin_lock_init(&ovpn->lock); + spin_lock_init(&ovpn->peers.lock); ++ mutex_init(&ovpn->napi_lock); + + ovpn->crypto_wq = alloc_workqueue("ovpn-crypto-wq-%s", + WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, 0, +diff --git a/drivers/net/ovpn-dco/ovpnstruct.h b/drivers/net/ovpn-dco/ovpnstruct.h +index 98f0953..bcedf8b 100644 +--- a/drivers/net/ovpn-dco/ovpnstruct.h ++++ b/drivers/net/ovpn-dco/ovpnstruct.h +@@ -13,6 +13,7 @@ + #include "peer.h" + + #include <uapi/linux/ovpn_dco.h> ++#include <linux/mutex.h> + #include <linux/spinlock.h> + #include <linux/workqueue.h> + +@@ -27,6 +28,9 @@ struct ovpn_struct { + /* protect writing to the ovpn_struct object */ + spinlock_t lock; + ++ /* protect NAPI add/delete operations */ ++ struct mutex napi_lock; ++ + /* workqueue used to schedule crypto work that may sleep */ + struct workqueue_struct *crypto_wq; + /* workqueue used to schedule generic event that may sleep or that need +diff --git a/drivers/net/ovpn-dco/peer.c b/drivers/net/ovpn-dco/peer.c +index 167fa62..14a5454 100644 +--- a/drivers/net/ovpn-dco/peer.c ++++ b/drivers/net/ovpn-dco/peer.c +@@ -36,6 +36,23 @@ static void ovpn_peer_expire(struct timer_list *t) + ovpn_peer_del(peer, OVPN_DEL_PEER_REASON_EXPIRED); + } + ++static void ovpn_peer_napi_add(struct ovpn_peer *peer) ++{ ++ mutex_lock(&peer->ovpn->napi_lock); ++ netif_napi_add_tx_weight(peer->ovpn->dev, &peer->napi, ovpn_napi_poll, ++ NAPI_POLL_WEIGHT); ++ napi_enable(&peer->napi); ++ mutex_unlock(&peer->ovpn->napi_lock); ++} ++ ++static void ovpn_peer_napi_del(struct ovpn_peer *peer) ++{ ++ mutex_lock(&peer->ovpn->napi_lock); ++ napi_disable(&peer->napi); ++ netif_napi_del(&peer->napi); ++ mutex_unlock(&peer->ovpn->napi_lock); ++} ++ + /* Construct a new peer */ + static struct ovpn_peer *ovpn_peer_create(struct ovpn_struct *ovpn, u32 id) + { +@@ -89,9 +106,7 @@ static struct ovpn_peer *ovpn_peer_create(struct ovpn_struct *ovpn, u32 id) + } + + /* configure and start NAPI */ +- netif_napi_add_tx_weight(ovpn->dev, &peer->napi, ovpn_napi_poll, +- NAPI_POLL_WEIGHT); +- napi_enable(&peer->napi); ++ ovpn_peer_napi_add(peer); + + dev_hold(ovpn->dev); + +@@ -224,8 +239,7 @@ static void ovpn_peer_release_rcu(struct rcu_head *head) + + void ovpn_peer_release(struct ovpn_peer *peer) + { +- napi_disable(&peer->napi); +- netif_napi_del(&peer->napi); ++ ovpn_peer_napi_del(peer); + + if (peer->sock) + ovpn_socket_put(peer->sock); diff -Nru openvpn-dco-dkms-0.0+git20241121/debian/patches/series openvpn-dco-dkms-0.0+git20241121/debian/patches/series --- openvpn-dco-dkms-0.0+git20241121/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 +++ openvpn-dco-dkms-0.0+git20241121/debian/patches/series 2026-06-23 23:58:52.000000000 +0200 @@ -0,0 +1,2 @@ +avoid-UAF-when-releasing-peer.patch +serialize-peer-NAPI-add-delete.patch

