Merge pull request #4181 from gilles-peskine-arm/net_poll-fd_setsize-2.7

Backport 2.7: Fix stack corruption in mbedtls_net_poll with large file descriptor
This commit is contained in:
Janos Follath 2021-03-04 12:15:42 +00:00 committed by GitHub
commit b266edaf2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 3 deletions

View File

@ -0,0 +1,3 @@
Security
* Fix a stack buffer overflow with mbedtls_net_recv_timeout() when given a
file descriptor that is beyond FD_SETSIZE. Reported by FigBug in #4169.

View File

@ -130,6 +130,7 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char
* *
* \return 0 if successful, or one of: * \return 0 if successful, or one of:
* MBEDTLS_ERR_NET_SOCKET_FAILED, * MBEDTLS_ERR_NET_SOCKET_FAILED,
* MBEDTLS_ERR_NET_UNKNOWN_HOST,
* MBEDTLS_ERR_NET_BIND_FAILED, * MBEDTLS_ERR_NET_BIND_FAILED,
* MBEDTLS_ERR_NET_LISTEN_FAILED * MBEDTLS_ERR_NET_LISTEN_FAILED
* *
@ -149,6 +150,8 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
* can be NULL if client_ip is null * can be NULL if client_ip is null
* *
* \return 0 if successful, or * \return 0 if successful, or
* MBEDTLS_ERR_NET_SOCKET_FAILED,
* MBEDTLS_ERR_NET_BIND_FAILED,
* MBEDTLS_ERR_NET_ACCEPT_FAILED, or * MBEDTLS_ERR_NET_ACCEPT_FAILED, or
* MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small,
* MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to
@ -219,16 +222,21 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len );
* 'timeout' seconds. If no error occurs, the actual amount * 'timeout' seconds. If no error occurs, the actual amount
* read is returned. * read is returned.
* *
* \note The current implementation of this function uses
* select() and returns an error if the file descriptor
* is \c FD_SETSIZE or greater.
*
* \param ctx Socket * \param ctx Socket
* \param buf The buffer to write to * \param buf The buffer to write to
* \param len Maximum length of the buffer * \param len Maximum length of the buffer
* \param timeout Maximum number of milliseconds to wait for data * \param timeout Maximum number of milliseconds to wait for data
* 0 means no timeout (wait forever) * 0 means no timeout (wait forever)
* *
* \return the number of bytes received, * \return The number of bytes received if successful.
* or a non-zero error code: * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out.
* MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out,
* MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal.
* Another negative error code (MBEDTLS_ERR_NET_xxx)
* for other failures.
* *
* \note This function will block (until data becomes available or * \note This function will block (until data becomes available or
* timeout is reached) even if the socket is set to * timeout is reached) even if the socket is set to

View File

@ -535,6 +535,13 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
if( fd < 0 ) if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
/* A limitation of select() is that it only works with file descriptors
* that are strictly less than FD_SETSIZE. This is a limitation of the
* fd_set type. Error out early, because attempting to call FD_SET on a
* large file descriptor is a buffer overflow on typical platforms. */
if( fd >= FD_SETSIZE )
return( MBEDTLS_ERR_NET_RECV_FAILED );
FD_ZERO( &read_fds ); FD_ZERO( &read_fds );
FD_SET( fd, &read_fds ); FD_SET( fd, &read_fds );