lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 18 Oct 2012 23:02:53 -0700
From:	Vijay Subramanian <subramanian.vijay@...il.com>
To:	enh <enh@...gle.com>
Cc:	Venkat Venkatsubra <venkat.x.venkatsubra@...cle.com>,
	netdev@...r.kernel.org, Eric Dumazet <eric.dumazet@...il.com>
Subject: Re: listen(2) backlog changes in or around Linux 3.1?

>> They all remain on ESTABLISHED state on the client side.
>
> yeah, that's what i see with netstat -t too.
>

> (https://android-review.googlesource.com/#/c/44563/), but i'd love to
> at least understand what's going on here, even if it's just that i
> have a fundamental misunderstanding of what the listen backlog is
> supposed to mean.
>

The listen backlog represents the number of received SYNs that have
not been processed i.e. for which a SYN-ACK has not been sent.
Actually, the number of SYNs
that can be pending for processing is actually backlog+1. With a
backlog of 1, there can be 2 SYNs that can be pending for processing.

Once a SYN is processed by the server socket (in LISTEN state) and a
syn-ack is sent back, a request_sock is created to represent it. Once
the client replies with the last step of connect() i.e. with  an ack,
a fully established socket is created. The number of queued
request-socks for a LISTEN socket can be much more than the backlog
limit given in listen() (which is 1 in your case). If after a short
period (after SYNACK_RETRIES), the three way handshake is not
completed, request_socks can be silently discarded.

When a SYN is received, it is processed by   tcp_v4_conn_request()
where we have..
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
 got drop;

So, for the SYN to be dropped, backlog limit must be exceeded _and_ we
must have recently accepted another SYN request. So, even when backlog
limit is exceeded, SYNs are processed and syn-acks are sent back. It
seems that the listen backlog limit is applied definitively only in
the third step in tcp_v4_syn_recv_sock() and not in the first step.
In  tcp_v4_syn_recv_sock(), we have
 if (sk_acceptq_is_full(sk))
                goto exit_overflow;

This prevents the socket from being created fully. On the client side
however, since the three way handshake has finished, the socket goes
into ESTABLISHED state which is what you see with netstat. In your
test case, typically 2 connections are in state where SYN has to be
processed  and rest are as request_sock where synacks have been sent.
However,
they may not become fully created sockets as they will fail in step 3
as described above.

man listen() says
" The  backlog  argument  defines  the maximum length to which the
queue of pending connections for sockfd may grow. " In your case where
backlog is 1, there can be a max of 2 pending connections (SYNs not
yet processed) and this is what we see. By this interpretation,
behavior seems correct.

Not sure if this behavior is a bug but the processing in
tcp_v4_conn_request()  does look suspicious. Should we terminate
earlier without doing three way hand shake?
Perhaps someone who knows this better can clarify.

Hope this helps.
Vijay
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ