Fix stack buffer overflow in net functions with large file descriptor

Fix a stack buffer overflow with mbedtls_net_poll() and
mbedtls_net_recv_timeout() when given a file descriptor that is beyond
FD_SETSIZE. The bug was due to not checking that the file descriptor
is within the range of an fd_set object.

Fix #4169

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2021-02-24 19:49:44 +01:00
parent b01ce91745
commit f604240b1b
2 changed files with 18 additions and 0 deletions

View File

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

View File

@ -496,6 +496,13 @@ int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
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
* up to 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_POLL_FAILED );
#if defined(__has_feature) #if defined(__has_feature)
#if __has_feature(memory_sanitizer) #if __has_feature(memory_sanitizer)
/* Ensure that memory sanitizers consider read_fds and write_fds as /* Ensure that memory sanitizers consider read_fds and write_fds as
@ -615,6 +622,13 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
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
* up to 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_POLL_FAILED );
FD_ZERO( &read_fds ); FD_ZERO( &read_fds );
FD_SET( fd, &read_fds ); FD_SET( fd, &read_fds );