From ddf437487901f61042fbd2b30b8c2a4b5a25134a Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 24 Feb 2021 19:49:44 +0100 Subject: [PATCH] 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 --- ChangeLog.d/net_poll-fd_setsize.txt | 4 ++++ library/net_sockets.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 ChangeLog.d/net_poll-fd_setsize.txt diff --git a/ChangeLog.d/net_poll-fd_setsize.txt b/ChangeLog.d/net_poll-fd_setsize.txt new file mode 100644 index 000000000..e4db8c7e3 --- /dev/null +++ b/ChangeLog.d/net_poll-fd_setsize.txt @@ -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. diff --git a/library/net_sockets.c b/library/net_sockets.c index 54c2b472f..375434abd 100644 --- a/library/net_sockets.c +++ b/library/net_sockets.c @@ -465,6 +465,13 @@ int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) if( fd < 0 ) 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 __has_feature(memory_sanitizer) /* Ensure that memory sanitizers consider read_fds and write_fds as @@ -584,6 +591,13 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, if( fd < 0 ) 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_SET( fd, &read_fds );