sshd gets stuck: select() in packet_read_seqnr waits indefinitely

Darren Tucker dtucker at zip.com.au
Thu Mar 15 13:43:47 EST 2007


On Wed, Mar 14, 2007 at 07:12:09PM -0600, Matt Day wrote:
> On Thu, Mar 15, 2007 at 11:14:16AM +1100, Darren Tucker wrote:
> > You could try the attached patch.
> 
> Oh, cool...thanks for the fast response!
> 
> I have a question about the patch. With it applied, packet_read_seqnr
> now reads:
> 
>         /* Wait for some data to arrive. */
>         while (select(connection_in + 1, setp, NULL, NULL,
>             packet_wait_tvp) == -1 &&
>             (errno == EAGAIN || errno == EINTR))
>                 ;
> 
>         /* Read data from the socket. */
>         len = read(connection_in, buf, sizeof(buf));
>         ...

> On FreeBSD, select() will return 0 upon timeout, so packet_read_seqnr
> would end up calling read() even though the descriptor isn't ready,
> so I think it would block.

The descriptor is O_NONBLOCK (set by packet_set_nonblocking()), so the
read() should return -1 with errno == EWOULDBLOCK or EAGAIN.

> Similarly, I don't see how a select() timeout would cause packet_write_wait
> to abort. Instead it would call packet_write_poll (which calls write())
> even though the descriptor isn't ready for writing. Am I missing something?

The next couple of lines after the ones you quoted are:

	if (len == 0) {
		logit("Connection closed by %.200s", get_remote_ipaddr());
		cleanup_exit(255);
	}
	if (len < 0)
		fatal("Read from socket failed: %.100s", strerror(errno));

len should be -1 in the case of a timeout, so that should kill the
connection (I've not tested it).

You could test for EWOULDBLOCK or EAGAIN and provide a more informative
error message, though.

-- 
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4  37C9 C982 80C7 8FF4 FA69
    Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.


More information about the openssh-unix-dev mailing list