From: David Carlier <devnexen@gmail.com>
To: netdev@vger.kernel.org
Cc: David Carlier <devnexen@gmail.com>,
Antonio Quartulli <antonio@openvpn.net>,
Sabrina Dubroca <sd@queasysnail.net>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH net 2/2] ovpn: respect peer refcount in CMD_NEW_PEER error path
Date: Tue, 12 May 2026 05:19:13 +0100 [thread overview]
Message-ID: <20260512042036.19870-3-devnexen@gmail.com> (raw)
In-Reply-To: <20260512042036.19870-1-devnexen@gmail.com>
ovpn_nl_peer_new_doit()'s error path calls ovpn_peer_release() directly
rather than ovpn_peer_put(), bypassing the kref. The accompanying
comment ("peer was not yet hashed, thus it is not used in any context")
holds for UDP but not for TCP.
For UDP, the ovpn_socket union uses the .ovpn arm and never points back
at a peer; UDP encap_recv looks up peers via the not-yet-populated
hashtables, so the new peer is unreachable until ovpn_peer_add()
publishes it.
For TCP, ovpn_socket_new() sets ovpn_sock->peer and
ovpn_tcp_socket_attach() publishes ovpn_sock via rcu_assign_sk_user_data().
From that moment until ovpn_socket_release() detaches in the error path,
the TCP fd is fully wired: userspace recvmsg / sendmsg / close / poll
on the fd, as well as the strparser-driven ovpn_tcp_rcv() path, can
reach the peer through sk_user_data -> ovpn_sock->peer and bump its
refcount via ovpn_peer_hold().
ovpn_tcp_socket_wait_finish() (called inside ovpn_socket_release())
drains strparser and the tx work, but does not synchronize with
userspace syscall callers that already hold a peer reference. If
ovpn_nl_peer_modify() or ovpn_peer_add() returns an error while such
a caller is in flight - notably an ovpn_tcp_recvmsg() blocked in
__skb_recv_datagram() on peer->tcp.user_queue - the direct
ovpn_peer_release() destroys the peer while the caller still holds
the reference, and the eventual ovpn_peer_put() from that caller
operates on freed memory.
Replace the direct destructor call with ovpn_peer_put() so the kref
correctly defers destruction until the last reference is dropped.
In the common case where no concurrent user is present, behaviour is
unchanged: the kref hits zero immediately and ovpn_peer_release_kref()
runs the same destructor.
Fixes: 11851cbd60ea ("ovpn: implement TCP transport")
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: David Carlier <devnexen@gmail.com>
---
drivers/net/ovpn/netlink.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c
index 291e2e5bb450..4c66c1ec497e 100644
--- a/drivers/net/ovpn/netlink.c
+++ b/drivers/net/ovpn/netlink.c
@@ -462,10 +462,12 @@ int ovpn_nl_peer_new_doit(struct sk_buff *skb, struct genl_info *info)
sock_release:
ovpn_socket_release(peer);
peer_release:
- /* release right away because peer was not yet hashed, thus it is not
- * used in any context
+ /* For UDP, the peer is unreachable until added to the hashtables, so
+ * dropping the initial reference is enough. For TCP, the peer may be
+ * concurrently reachable via sk_user_data->peer until
+ * ovpn_socket_release() detaches; rely on the refcount.
*/
- ovpn_peer_release(peer);
+ ovpn_peer_put(peer);
return ret;
}
--
2.53.0
next prev parent reply other threads:[~2026-05-12 4:20 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260512042036.19870-1-devnexen@gmail.com>
2026-05-12 4:19 ` [PATCH net 1/2] ovpn: tcp - use cached peer pointer in ovpn_tcp_close() David Carlier
2026-05-12 4:29 ` Eric Dumazet
2026-05-12 4:56 ` David CARLIER
2026-05-12 7:29 ` Antonio Quartulli
2026-05-12 13:55 ` Antonio Quartulli
2026-05-12 14:11 ` Sabrina Dubroca
2026-05-12 14:17 ` Antonio Quartulli
2026-05-12 15:04 ` Sabrina Dubroca
2026-05-12 4:19 ` David Carlier [this message]
2026-05-12 7:33 ` [PATCH net 2/2] ovpn: respect peer refcount in CMD_NEW_PEER error path Antonio Quartulli
2026-05-12 15:13 ` Sabrina Dubroca
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260512042036.19870-3-devnexen@gmail.com \
--to=devnexen@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=antonio@openvpn.net \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sd@queasysnail.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox