xref: /linux/drivers/net/ovpn/socket.c (revision 59e6295fac26b8e85c1ea859cdd89fa1e47519d7)
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 
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  */
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  */
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 
110 static bool ovpn_socket_hold(struct ovpn_socket *sock)
111 {
112 	return kref_get_unless_zero(&sock->refcount);
113 }
114 
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  */
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 			/* something else filled the sk_user_data without
166 			 * setting the encap_type. Reject the socket.
167 			 */
168 			if (!type) {
169 				ovpn_sock = ERR_PTR(-EBUSY);
170 				rcu_read_unlock();
171 				goto sock_release;
172 			}
173 
174 			/* socket owned by another ovpn instance, we can't use it */
175 			if (ovpn_sock->ovpn != peer->ovpn) {
176 				ovpn_sock = ERR_PTR(-EBUSY);
177 				rcu_read_unlock();
178 				goto sock_release;
179 			}
180 
181 			/* this socket is already owned by this instance,
182 			 * therefore we can increase the refcounter and
183 			 * use it as expected
184 			 */
185 			if (WARN_ON(!ovpn_socket_hold(ovpn_sock))) {
186 				/* this should never happen because setting
187 				 * the refcnt to 0 and detaching the socket
188 				 * is expected to be atomic
189 				 */
190 				ovpn_sock = ERR_PTR(-EAGAIN);
191 				rcu_read_unlock();
192 				goto sock_release;
193 			}
194 
195 			rcu_read_unlock();
196 			goto sock_release;
197 		}
198 		rcu_read_unlock();
199 	}
200 
201 	/* socket is not owned: attach to this ovpn instance */
202 
203 	ovpn_sock = kzalloc_obj(*ovpn_sock);
204 	if (!ovpn_sock) {
205 		ovpn_sock = ERR_PTR(-ENOMEM);
206 		goto sock_release;
207 	}
208 
209 	ovpn_sock->sk = sk;
210 	kref_init(&ovpn_sock->refcount);
211 
212 	/* TCP sockets are per-peer, therefore they are linked to their unique
213 	 * peer
214 	 */
215 	if (sk->sk_protocol == IPPROTO_TCP) {
216 		INIT_WORK(&ovpn_sock->tcp_tx_work, ovpn_tcp_tx_work);
217 		ovpn_sock->peer = peer;
218 		ovpn_peer_hold(peer);
219 	} else if (sk->sk_protocol == IPPROTO_UDP) {
220 		/* in UDP we only link the ovpn instance since the socket is
221 		 * shared among multiple peers
222 		 */
223 		ovpn_sock->ovpn = peer->ovpn;
224 		netdev_hold(peer->ovpn->dev, &ovpn_sock->dev_tracker,
225 			    GFP_KERNEL);
226 	}
227 
228 	/* the newly created ovpn_socket is holding reference to sk,
229 	 * therefore we increase its refcounter.
230 	 *
231 	 * This ovpn_socket instance is referenced by all peers
232 	 * using the same socket.
233 	 *
234 	 * ovpn_socket_release() will take care of dropping the reference.
235 	 */
236 	sock_hold(sk);
237 
238 	ret = ovpn_socket_attach(ovpn_sock, sock, peer);
239 	if (ret < 0) {
240 		if (sk->sk_protocol == IPPROTO_TCP)
241 			ovpn_peer_put(peer);
242 		else if (sk->sk_protocol == IPPROTO_UDP)
243 			netdev_put(peer->ovpn->dev, &ovpn_sock->dev_tracker);
244 
245 		sock_put(sk);
246 		kfree(ovpn_sock);
247 		ovpn_sock = ERR_PTR(ret);
248 	}
249 
250 sock_release:
251 	release_sock(sk);
252 	return ovpn_sock;
253 }
254