@@ -149,13 +149,17 @@ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind,
struct flowi4 fl = {
.saddr = bind->local.ipv4.s_addr,
.daddr = bind->remote.in4.sin_addr.s_addr,
- .fl4_sport = inet_sk(sk)->inet_sport,
+ .fl4_sport = READ_ONCE(inet_sk(sk)->inet_sport),
.fl4_dport = bind->remote.in4.sin_port,
.flowi4_proto = sk->sk_protocol,
.flowi4_mark = sk->sk_mark,
};
int ret;
+ /* an uninitialized socket or connect(AF_UNSPEC) can cause this */
+ if (unlikely(!fl.fl4_sport))
+ return -EADDRNOTAVAIL;
+
local_bh_disable();
rt = dst_cache_get_ip4(cache, &fl.saddr);
if (rt)
@@ -226,13 +230,17 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind,
struct flowi6 fl = {
.saddr = bind->local.ipv6,
.daddr = bind->remote.in6.sin6_addr,
- .fl6_sport = inet_sk(sk)->inet_sport,
+ .fl6_sport = READ_ONCE(inet_sk(sk)->inet_sport),
.fl6_dport = bind->remote.in6.sin6_port,
.flowi6_proto = sk->sk_protocol,
.flowi6_mark = sk->sk_mark,
.flowi6_oif = bind->remote.in6.sin6_scope_id,
};
+ /* an uninitialized socket or connect(AF_UNSPEC) can cause this */
+ if (unlikely(!fl.fl6_sport))
+ return -EADDRNOTAVAIL;
+
local_bh_disable();
dst = dst_cache_get_ip6(cache, &fl.saddr);
if (dst)
ovpn operates on a userspace-owned UDP socket, which may be manipulated in various ways by userspace. If the socket is never bound, connected, or used for communication, it may not have a source port assigned. Similarly, if the socket was connect()'ed to AF_INET or AF_INET6, it can be disconnected by connect() with AF_UNSPEC, which resets the source port unless the socket was explicitly bound. Since we must not transmit packets with source port 0, gate UDP TX on the presence of a valid source port and drop packets otherwise. To avoid ambiguity, sample the current source port once before route lookup and header build and enforce the check on that value. Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)") Signed-off-by: Ralf Lici <ralf@mandelbit.com> --- drivers/net/ovpn/udp.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)