1 // SPDX-License-Identifier: GPL-2.0
2 /* OpenVPN data channel offload
3 *
4 * Copyright (C) 2020-2025 OpenVPN, Inc.
5 *
6 * Author: James Yonan <james@openvpn.net>
7 * Antonio Quartulli <antonio@openvpn.net>
8 */
9
10 #include <linux/net.h>
11 #include <linux/netdevice.h>
12 #include <linux/udp.h>
13
14 #include "ovpnpriv.h"
15 #include "main.h"
16 #include "io.h"
17 #include "peer.h"
18 #include "socket.h"
19 #include "tcp.h"
20 #include "udp.h"
21
ovpn_socket_release_kref(struct kref * kref)22 static void ovpn_socket_release_kref(struct kref *kref)
23 {
24 struct ovpn_socket *sock = container_of(kref, struct ovpn_socket,
25 refcount);
26
27 if (sock->sk->sk_protocol == IPPROTO_UDP)
28 ovpn_udp_socket_detach(sock);
29 else if (sock->sk->sk_protocol == IPPROTO_TCP)
30 ovpn_tcp_socket_detach(sock);
31 }
32
33 /**
34 * ovpn_socket_put - decrease reference counter
35 * @peer: peer whose socket reference counter should be decreased
36 * @sock: the RCU protected peer socket
37 *
38 * This function is only used internally. Users willing to release
39 * references to the ovpn_socket should use ovpn_socket_release()
40 *
41 * Return: true if the socket was released, false otherwise
42 */
ovpn_socket_put(struct ovpn_peer * peer,struct ovpn_socket * sock)43 static bool ovpn_socket_put(struct ovpn_peer *peer, struct ovpn_socket *sock)
44 {
45 return kref_put(&sock->refcount, ovpn_socket_release_kref);
46 }
47
48 /**
49 * ovpn_socket_release - release resources owned by socket user
50 * @peer: peer whose socket should be released
51 *
52 * This function should be invoked when the peer is being removed
53 * and wants to drop its link to the socket.
54 *
55 * In case of UDP, the detach routine will drop a reference to the
56 * ovpn netdev, pointed by the ovpn_socket.
57 *
58 * In case of TCP, releasing the socket will cause dropping
59 * the refcounter for the peer it is linked to, thus allowing the peer
60 * disappear as well.
61 *
62 * This function is expected to be invoked exactly once per peer
63 *
64 * NOTE: this function may sleep
65 */
ovpn_socket_release(struct ovpn_peer * peer)66 void ovpn_socket_release(struct ovpn_peer *peer)
67 {
68 struct ovpn_socket *sock;
69 bool released;
70
71 might_sleep();
72
73 sock = rcu_replace_pointer(peer->sock, NULL, true);
74 /* release may be invoked after socket was detached */
75 if (!sock)
76 return;
77
78 /* Drop the reference while holding the sock lock to avoid
79 * concurrent ovpn_socket_new call to mess up with a partially
80 * detached socket.
81 *
82 * Holding the lock ensures that a socket with refcnt 0 is fully
83 * detached before it can be picked by a concurrent reader.
84 */
85 lock_sock(sock->sk);
86 released = ovpn_socket_put(peer, sock);
87 release_sock(sock->sk);
88
89 /* align all readers with sk_user_data being NULL */
90 synchronize_rcu();
91
92 /* following cleanup should happen with lock released */
93 if (released) {
94 if (sock->sk->sk_protocol == IPPROTO_UDP) {
95 netdev_put(sock->ovpn->dev, &sock->dev_tracker);
96 } else if (sock->sk->sk_protocol == IPPROTO_TCP) {
97 /* wait for TCP jobs to terminate */
98 ovpn_tcp_socket_wait_finish(sock);
99 ovpn_peer_put(sock->peer);
100 }
101 /* drop reference acquired in ovpn_socket_new() */
102 sock_put(sock->sk);
103 /* we can call plain kfree() because we already waited one RCU
104 * period due to synchronize_rcu()
105 */
106 kfree(sock);
107 }
108 }
109
ovpn_socket_hold(struct ovpn_socket * sock)110 static bool ovpn_socket_hold(struct ovpn_socket *sock)
111 {
112 return kref_get_unless_zero(&sock->refcount);
113 }
114
ovpn_socket_attach(struct ovpn_socket * ovpn_sock,struct socket * sock,struct ovpn_peer * peer)115 static int ovpn_socket_attach(struct ovpn_socket *ovpn_sock,
116 struct socket *sock,
117 struct ovpn_peer *peer)
118 {
119 if (sock->sk->sk_protocol == IPPROTO_UDP)
120 return ovpn_udp_socket_attach(ovpn_sock, sock, peer->ovpn);
121 else if (sock->sk->sk_protocol == IPPROTO_TCP)
122 return ovpn_tcp_socket_attach(ovpn_sock, peer);
123
124 return -EOPNOTSUPP;
125 }
126
127 /**
128 * ovpn_socket_new - create a new socket and initialize it
129 * @sock: the kernel socket to embed
130 * @peer: the peer reachable via this socket
131 *
132 * Return: an openvpn socket on success or a negative error code otherwise
133 */
ovpn_socket_new(struct socket * sock,struct ovpn_peer * peer)134 struct ovpn_socket *ovpn_socket_new(struct socket *sock, struct ovpn_peer *peer)
135 {
136 struct ovpn_socket *ovpn_sock;
137 struct sock *sk = sock->sk;
138 int ret;
139
140 lock_sock(sk);
141
142 /* a TCP socket can only be owned by a single peer, therefore there
143 * can't be any other user
144 */
145 if (sk->sk_protocol == IPPROTO_TCP && sk->sk_user_data) {
146 ovpn_sock = ERR_PTR(-EBUSY);
147 goto sock_release;
148 }
149
150 /* a UDP socket can be shared across multiple peers, but we must make
151 * sure it is not owned by something else
152 */
153 if (sk->sk_protocol == IPPROTO_UDP) {
154 u8 type = READ_ONCE(udp_sk(sk)->encap_type);
155
156 /* socket owned by other encapsulation module */
157 if (type && type != UDP_ENCAP_OVPNINUDP) {
158 ovpn_sock = ERR_PTR(-EBUSY);
159 goto sock_release;
160 }
161
162 rcu_read_lock();
163 ovpn_sock = rcu_dereference_sk_user_data(sk);
164 if (ovpn_sock) {
165 /* socket owned by another ovpn instance, we can't use it */
166 if (ovpn_sock->ovpn != peer->ovpn) {
167 ovpn_sock = ERR_PTR(-EBUSY);
168 rcu_read_unlock();
169 goto sock_release;
170 }
171
172 /* this socket is already owned by this instance,
173 * therefore we can increase the refcounter and
174 * use it as expected
175 */
176 if (WARN_ON(!ovpn_socket_hold(ovpn_sock))) {
177 /* this should never happen because setting
178 * the refcnt to 0 and detaching the socket
179 * is expected to be atomic
180 */
181 ovpn_sock = ERR_PTR(-EAGAIN);
182 rcu_read_unlock();
183 goto sock_release;
184 }
185
186 rcu_read_unlock();
187 goto sock_release;
188 }
189 rcu_read_unlock();
190 }
191
192 /* socket is not owned: attach to this ovpn instance */
193
194 ovpn_sock = kzalloc(sizeof(*ovpn_sock), GFP_KERNEL);
195 if (!ovpn_sock) {
196 ovpn_sock = ERR_PTR(-ENOMEM);
197 goto sock_release;
198 }
199
200 ovpn_sock->sk = sk;
201 kref_init(&ovpn_sock->refcount);
202
203 /* the newly created ovpn_socket is holding reference to sk,
204 * therefore we increase its refcounter.
205 *
206 * This ovpn_socket instance is referenced by all peers
207 * using the same socket.
208 *
209 * ovpn_socket_release() will take care of dropping the reference.
210 */
211 sock_hold(sk);
212
213 ret = ovpn_socket_attach(ovpn_sock, sock, peer);
214 if (ret < 0) {
215 sock_put(sk);
216 kfree(ovpn_sock);
217 ovpn_sock = ERR_PTR(ret);
218 goto sock_release;
219 }
220
221 /* TCP sockets are per-peer, therefore they are linked to their unique
222 * peer
223 */
224 if (sk->sk_protocol == IPPROTO_TCP) {
225 INIT_WORK(&ovpn_sock->tcp_tx_work, ovpn_tcp_tx_work);
226 ovpn_sock->peer = peer;
227 ovpn_peer_hold(peer);
228 } else if (sk->sk_protocol == IPPROTO_UDP) {
229 /* in UDP we only link the ovpn instance since the socket is
230 * shared among multiple peers
231 */
232 ovpn_sock->ovpn = peer->ovpn;
233 netdev_hold(peer->ovpn->dev, &ovpn_sock->dev_tracker,
234 GFP_KERNEL);
235 }
236
237 rcu_assign_sk_user_data(sk, ovpn_sock);
238 sock_release:
239 release_sock(sk);
240 return ovpn_sock;
241 }
242