Re: unix_stream_connect and socket address resolution
From: David Laight <hidden>
Date: 2026-07-22 10:05:26
Also in:
linux-security-module, lkml
On Tue, 21 Jul 2026 16:37:07 -0400 "John Ericson" [off-list ref] wrote:
quoted hunk ↗ jump to hunk
In case this is useful or interesting to anyone, I deep a some history spelunking, and the restart logic in question seems to date back to Import 2.2.4pre6: https://github.com/tbodt/linux-history/commit/7d4fc34b9bbc0a14d3e5f6b2f978373422e1ca8a#diff-0553d076c243e06ae312480cb8cb52f1cebe1d80fc099d3842593e12c9e0d4f3 ---@@ -673,9 +703,25 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, we will have to recheck all again in any case. */ +restart: /* Find listening sock */ other=unix_find_other(sunaddr, addr_len, sk->type, hash, &err); + if (!other) + return -ECONNREFUSED; + + while (other->ack_backlog >= other->max_ack_backlog) { + unix_unlock(other);
This unlocks the socket - I doubt it makes sense to sleep with it locked.
+ if (other->dead || other->state != TCP_LISTEN) + return -ECONNREFUSED;
Those look like potential UAF. Hopefully changed in the current code!
+ if (flags & O_NONBLOCK) + return -EAGAIN; + interruptible_sleep_on(&unix_ack_wqueue); + if (signal_pending(current)) + return -ERESTARTSYS; + goto restart;
Since 'other' was unlocked the search must be repated. David
quoted hunk ↗ jump to hunk
+ } + /* create new sock for complete connection */ newsk = unix_create1(NULL, 1);@@ -704,7 +750,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, /* Check that listener is in valid state. */ err = -ECONNREFUSED; - if (other == NULL || other->dead || other->state != TCP_LISTEN) + if (other->dead || other->state != TCP_LISTEN) goto out; err = -ENOMEM; ---My question can be basically restated: why should the `restart` label not go *after* the `unix_find_other` call? Cheers, John