mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
Included fixes:
* ensure keepalive timestamps are computed using monotonic source * avoid UAF in unlock_ovpn() when iterating over release_list * fix memleak in selftest tool * ensure reference to peer is acquired before scheduling worker (which may drop the not-yet-taken ref) * fix refcount leak in case of concurrent TX and RX TCP error * fix potential refcount unbalance in case of sock release in P2P mode -----BEGIN PGP SIGNATURE----- iJEEABYIADkWIQQr0db7q+Rc7Zog28Fc8QQzwdnOtwUCal4xNRsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDIACgkQXPEEM8HZzrcjWQEAzhUfvdvKlB0R3IjYs5ze xUocdtTNVf3B2mOzRDMeu9oA/0PlyHorMDIi5l4ffiz+yzqbsul3929KjsRwTWnd E8gI =sQH6 -----END PGP SIGNATURE----- Merge tag 'ovpn-net-20260720' of https://github.com/OpenVPN/ovpn-net-next Antonio Quartulli says: ==================== Included fixes: * ensure keepalive timestamps are computed using monotonic source * avoid UAF in unlock_ovpn() when iterating over release_list * fix memleak in selftest tool * ensure reference to peer is acquired before scheduling worker (which may drop the not-yet-taken ref) * fix refcount leak in case of concurrent TX and RX TCP error * fix potential refcount unbalance in case of sock release in P2P mode * tag 'ovpn-net-20260720' of https://github.com/OpenVPN/ovpn-net-next: ovpn: use monotonic clock for peer keepalive timeouts ovpn: fix use after free in unlock_ovpn() selftests/net: ovpn: fix getaddrinfo memory leak in ovpn_parse_remote() ovpn: hold peer before scheduling keepalive work ovpn: fix peer refcount leak in TCP error paths ovpn: avoid putting unrelated P2P peer on socket release ==================== Link: https://patch.msgid.link/20260720144131.3657121-1-antonio@openvpn.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
d73a2e81f3
|
|
@ -142,7 +142,7 @@ void ovpn_decrypt_post(void *data, int ret)
|
|||
}
|
||||
|
||||
/* keep track of last received authenticated packet for keepalive */
|
||||
WRITE_ONCE(peer->last_recv, ktime_get_real_seconds());
|
||||
WRITE_ONCE(peer->last_recv, ktime_get_boottime_seconds());
|
||||
|
||||
rcu_read_lock();
|
||||
sock = rcu_dereference(peer->sock);
|
||||
|
|
@ -294,7 +294,7 @@ void ovpn_encrypt_post(void *data, int ret)
|
|||
|
||||
ovpn_peer_stats_increment_tx(&peer->link_stats, orig_len);
|
||||
/* keep track of last sent packet for keepalive */
|
||||
WRITE_ONCE(peer->last_sent, ktime_get_real_seconds());
|
||||
WRITE_ONCE(peer->last_sent, ktime_get_boottime_seconds());
|
||||
/* skb passed down the stack - don't free it */
|
||||
skb = NULL;
|
||||
err_unlock:
|
||||
|
|
|
|||
|
|
@ -26,11 +26,12 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,
|
|||
struct llist_head *release_list)
|
||||
__releases(&ovpn->lock)
|
||||
{
|
||||
struct ovpn_peer *peer;
|
||||
struct ovpn_peer *peer, *next;
|
||||
|
||||
spin_unlock_bh(&ovpn->lock);
|
||||
|
||||
llist_for_each_entry(peer, release_list->first, release_entry) {
|
||||
llist_for_each_entry_safe(peer, next, release_list->first,
|
||||
release_entry) {
|
||||
ovpn_socket_release(peer);
|
||||
ovpn_peer_put(peer);
|
||||
}
|
||||
|
|
@ -44,7 +45,7 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,
|
|||
*/
|
||||
void ovpn_peer_keepalive_set(struct ovpn_peer *peer, u32 interval, u32 timeout)
|
||||
{
|
||||
time64_t now = ktime_get_real_seconds();
|
||||
time64_t now = ktime_get_boottime_seconds();
|
||||
|
||||
netdev_dbg(peer->ovpn->dev,
|
||||
"scheduling keepalive for peer %u: interval=%u timeout=%u\n",
|
||||
|
|
@ -1167,7 +1168,6 @@ static void ovpn_peer_release_p2p(struct ovpn_priv *ovpn, struct sock *sk,
|
|||
ovpn_sock = rcu_access_pointer(peer->sock);
|
||||
if (!ovpn_sock || ovpn_sock->sk != sk) {
|
||||
spin_unlock_bh(&ovpn->lock);
|
||||
ovpn_peer_put(peer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1285,8 +1285,10 @@ static time64_t ovpn_peer_keepalive_work_single(struct ovpn_peer *peer,
|
|||
netdev_dbg(peer->ovpn->dev,
|
||||
"sending keepalive to peer %u\n",
|
||||
peer->id);
|
||||
if (schedule_work(&peer->keepalive_work))
|
||||
ovpn_peer_hold(peer);
|
||||
if (WARN_ON(!ovpn_peer_hold(peer)))
|
||||
return 0;
|
||||
if (!schedule_work(&peer->keepalive_work))
|
||||
ovpn_peer_put(peer);
|
||||
}
|
||||
|
||||
if (next_run1 < next_run2)
|
||||
|
|
@ -1357,7 +1359,7 @@ void ovpn_peer_keepalive_work(struct work_struct *work)
|
|||
{
|
||||
struct ovpn_priv *ovpn = container_of(work, struct ovpn_priv,
|
||||
keepalive_work.work);
|
||||
time64_t next_run = 0, now = ktime_get_real_seconds();
|
||||
time64_t next_run = 0, now = ktime_get_boottime_seconds();
|
||||
LLIST_HEAD(release_list);
|
||||
|
||||
spin_lock_bh(&ovpn->lock);
|
||||
|
|
|
|||
|
|
@ -151,7 +151,8 @@ static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)
|
|||
/* take reference for deferred peer deletion. should never fail */
|
||||
if (WARN_ON(!ovpn_peer_hold(peer)))
|
||||
goto err_nopeer;
|
||||
schedule_work(&peer->tcp.defer_del_work);
|
||||
if (!schedule_work(&peer->tcp.defer_del_work))
|
||||
ovpn_peer_put(peer);
|
||||
ovpn_dev_dstats_rx_dropped(peer->ovpn->dev);
|
||||
err_nopeer:
|
||||
kfree_skb(skb);
|
||||
|
|
@ -283,7 +284,8 @@ static void ovpn_tcp_send_sock(struct ovpn_peer *peer, struct sock *sk)
|
|||
* stream therefore we abort the connection
|
||||
*/
|
||||
ovpn_peer_hold(peer);
|
||||
schedule_work(&peer->tcp.defer_del_work);
|
||||
if (!schedule_work(&peer->tcp.defer_del_work))
|
||||
ovpn_peer_put(peer);
|
||||
|
||||
/* we bail out immediately and keep tx_in_progress set
|
||||
* to true. This way we prevent more TX attempts
|
||||
|
|
|
|||
|
|
@ -1785,7 +1785,7 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host,
|
|||
const char *service, const char *vpnip)
|
||||
{
|
||||
int ret;
|
||||
struct addrinfo *result;
|
||||
struct addrinfo *result = NULL;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = ovpn->sa_family,
|
||||
.ai_socktype = SOCK_DGRAM,
|
||||
|
|
@ -1809,6 +1809,8 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host,
|
|||
}
|
||||
|
||||
memcpy(&ovpn->remote, result->ai_addr, result->ai_addrlen);
|
||||
freeaddrinfo(result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
if (vpnip) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user