From 8336a3b27d9ef644e13cf792d108f4c10b54690b Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Sat, 6 Jun 2026 15:57:01 -0400 Subject: [PATCH] fix(sock_hc): only report releases for listening TCP sockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit igloo_sock_release fired for any socket release, including accepted and connected sockets that share a listener's local port. A client disconnecting from a service therefore looked like the listener itself closing — most damaging for loopback services bound to 127.0.0.1, whose connections share the bound address. Gate TCP releases on sk_state == TCP_LISTEN so only genuine listener shutdowns are reported; UDP behavior is unchanged. This pairs with the host-side NetBinds lifecycle tracking in rehosting/penguin. --- src/hooks/sock_hc.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/hooks/sock_hc.c b/src/hooks/sock_hc.c index a0c0a37..04f1dc5 100644 --- a/src/hooks/sock_hc.c +++ b/src/hooks/sock_hc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "igloo.h" #include #include @@ -91,26 +92,32 @@ void igloo_sock_release(struct socket *sock){ if (sk->sk_family == AF_INET) { char buffer[23]; struct inet_sock *inet = inet_sk(sk); - port = ntohs(inet->inet_sport); - if (port != 0){ - __be32 ip = inet->inet_saddr; - short is_stream = (sk->sk_type == SOCK_STREAM); + short is_stream = (sk->sk_type == SOCK_STREAM); + port = ntohs(inet->inet_sport); + // For TCP, only report listening sockets closing. Accepted and + // connected sockets share the listener's local port, so reporting + // their teardown would emit spurious release events for a service + // that is still listening. + if (port != 0 && (!is_stream || sk->sk_state == TCP_LISTEN)){ + __be32 ip = inet->inet_saddr; snprintf(buffer, sizeof(buffer), "%pI4:%u", &ip, port); - e = igloo_hypercall2(IGLOO_IPV4_RELEASE, (unsigned long)&buffer, (unsigned long)is_stream); + e = igloo_hypercall2(IGLOO_IPV4_RELEASE, (unsigned long)&buffer, (unsigned long)is_stream); } } else if (sk->sk_family == AF_INET6) { char buffer[49]; struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *ipv6_s = inet6_sk(sk); + short is_stream = (sk->sk_type == SOCK_STREAM); port = ntohs(inet->inet_sport); - if (port != 0){ + // As above: for TCP only report listeners, not accepted/connected + // sockets that share the listener's local port. + if (port != 0 && (!is_stream || sk->sk_state == TCP_LISTEN)){ struct in6_addr *ip6 = &ipv6_s->saddr; - short is_stream = (sk->sk_type == SOCK_STREAM); snprintf(buffer, sizeof(buffer), "[%pI6c]:%u", ip6, port); - + e = igloo_hypercall2(IGLOO_IPV6_RELEASE, (unsigned long)&buffer, (unsigned long)is_stream); } }