Re: unix_stream_connect and socket address resolution

From: David Laight

Date: Wed Jul 22 2026 - 06:08:32 EST


On Tue, 21 Jul 2026 16:37:07 -0400
"John Ericson" <mail@xxxxxxxxxxxxxx> wrote:

> 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

> + }
> +
> /* 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
>