SSL_read empty -> close?

Michael Wojcik Michael.Wojcik at microfocus.com
Thu Nov 3 17:36:05 UTC 2022


> From: Felipe Gasper <felipe at felipegasper.com>
> Sent: Thursday, 3 November, 2022 10:43
> >
> > And your description looks wrong anyway: shutdown(SHUT_RD) has
> > implementation-defined behavior for TCP sockets (because TCP does not
> > announce the read side of half-close to the peer), and on Linux causes
> > blocked receives and subsequent receives to return 0 (according to references
> 
> perl -MSocket -MIO::Socket::INET -e'my $s = IO::Socket::INET->new( Server =>
> 1, Listen => 1 ) or die; my $port = $s->sockport(); my $c = IO::Socket::INET-
> >new("localhost:$port") or die; syswrite $c, "hello"; my $sc = $s->accept();
> shutdown($sc, SHUT_RD); sysread $sc, my $buf, 512 or die $!; print $buf'
> 
> ^^ The above, I believe, demonstrates to the contrary: the read buffer is
> populated prior to shutdown and drained afterward.

As I noted, I hadn't tested it. The Linux man page is ambiguous:

   If how is SHUT_RD, further receptions will be disallowed.

It doesn't define "receptions". It's entirely possible that SHUT_RD will cause the stack to reject further application data (i.e. packets that increment the sequence number for anything other than ACK) from the peer, but permit the socket owner to continue to receive already-buffered data. That's arguably a poor implementation, and not what the man page appears to imply. And it looks to be in conflict with the Single UNIX Specification Issue 7 (not that Linux claims to be UNIX-conformant), which states that SHUT_SD "Disables further receive operations"; "operations" certainly seems to refer to actions taken by the caller, not by the peer.

There is a fair bit of debate about this online, and a number of people opine that the Linux behavior is correct, and SUS (they often refer to "POSIX", but POSIX has been superseded by SUS) is wrong. Others disagree.

The Linux kernel does take some action for a TCP socket that has SHUT_RD requested for it, but the behavior is not simple. (One SO comment mentions it causes it to exit the read loop in tcp_splice_read(), for example.) I'd be leery about relying on it.

I'm not sure how shutdown(SHUT_RD) is useful in the case of a TCP socket being used for TLS, to be perfectly honest. If the application protocol delimits messages properly and is half-duplex (request/response), then one side should know that no more data is expected and the other can detect incomplete messages, so there's likely no issue. If not, there's no way to guarantee you haven't encountered an incomplete message in bounded time (FPL Theorem applies). SHUT_RD does not signal the peer, so the peer can still get a RST if it continues to send. Perhaps I'm missing something, but I don't see what failure mode is being avoided by using SHUT_RD.

-- 
Michael Wojcik


More information about the openssl-users mailing list