Skip to content
This repository was archived by the owner on Jan 20, 2025. It is now read-only.

Fix improper _recv() callback return when ssl layer returned SSL_CLOSE_NOTIFY #84

Merged
merged 1 commit into from
Jul 24, 2018

Conversation

Adam5Wu
Copy link
Contributor

@Adam5Wu Adam5Wu commented Feb 8, 2018

With AsynClient, when remote initiated disconnect, tcp_ssl_read() will return SSL_CLOSE_NOTIFY.
However, at this moment, the pbuf has already been freed, and thus the _recv() callback should return ERR_OK so that LwIP can properly discard the buffer reference.

Otherwise, LwIP2 will think the data is not consumed, and attempt to maintain it in refused_data, and ultimately cause a double free and crash later.

On LwIP1, this is still an error, but it is likely to not cause any problem because LwIP1 does not attempt to maintain the unconsumed refused_data, instead it just print an assert message and overwrite the pointer with a new piece of data.

For the changes, there are three lines, only one line in src/ESPAsyncTCP.cpp directly related to this bug;
The other two lines are nice-to-have:
The second line in src/tcp_axtls.c is there just to keep a peace of mind;
The thrid line in src/tcp_axtls.h solves C99 compiler complaint of unknown bool type.

@@ -395,7 +395,7 @@ err_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, err_t err) {
ASYNC_TCP_DEBUG("_recv err: %d\n", read_bytes);
_close();
}
return read_bytes;
//return read_bytes;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we return error instead of saying ERR_OK?

Copy link
Contributor Author

@Adam5Wu Adam5Wu Feb 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really:

  1. if tcp_ssl_read() returns SSL_CLOSE_NOTIFY
    • The pbuf has been freed in tcp_ssl_read(), so LwIP should not try to further maintain it, and
    • Freeing pbuf in tcp_ssl_read() is a good choice because by definition of this signal, we are closing the connection anyway.
  2. if tcp_ssl_read() returns other error code
    • The block above the return is closing the connection anyway, so we don't care the left over data in pbuf
    • There are two code paths in tcp_ssl_read(), one frees the pbuf, one does not (handshake error)
      • For the code path that does not free pbuf, a reference is left in fd_data->tcp_pbuf, which will be freed when tcp_ssl_free() is called later.
    • Therefore, it is still necessary and correct to let LwIP not further maintain the pbuf.

So, in short, when we run into read_bytes < 0 situation, we will be closing the connection one way or another, and it is best to let LwIP give up ownership of the current pbuf.

And the easiest way to let LwIP do what we want is to return ERR_OK.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a different way to look at it, SSL belongs to "upper" layer and TCP belongs to "lower" layer.

SSL_CLOSE_NOTIFY is an upper layer signal, it may mean some abnormal situation, only to the SSL layer.

To the lower TCP layer, everything is normal -- the TCP layer successfully delivered the close notification signal to the SSL layer, hence ERR_OK.

@ilyary
Copy link

ilyary commented Mar 19, 2018

Please, raise version in library.json: "version": "1.1.3" to be updated by PlatformIO package manager

@me-no-dev me-no-dev merged commit 649dd36 into me-no-dev:master Jul 24, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants