1/* BEGIN_HEADER */ 2 3#include "mbedtls/net_sockets.h" 4 5#if defined(unix) || defined(__unix__) || defined(__unix) || \ 6 defined(__APPLE__) || defined(__QNXNTO__) || \ 7 defined(__HAIKU__) || defined(__midipix__) 8#define MBEDTLS_PLATFORM_IS_UNIXLIKE 9#endif 10 11#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE) 12#include <sys/resource.h> 13#include <sys/stat.h> 14#include <sys/time.h> 15#include <sys/types.h> 16#include <fcntl.h> 17#include <unistd.h> 18#endif 19 20 21#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE) 22/** Open a file on the given file descriptor. 23 * 24 * This is disruptive if there is already something open on that descriptor. 25 * Caller beware. 26 * 27 * \param ctx An initialized, but unopened socket context. 28 * On success, it refers to the opened file (\p wanted_fd). 29 * \param wanted_fd The desired file descriptor. 30 * 31 * \return \c 0 on succes, a negative error code on error. 32 */ 33static int open_file_on_fd( mbedtls_net_context *ctx, int wanted_fd ) 34{ 35 int got_fd = open( "/dev/null", O_RDONLY ); 36 TEST_ASSERT( got_fd >= 0 ); 37 if( got_fd != wanted_fd ) 38 { 39 TEST_ASSERT( dup2( got_fd, wanted_fd ) >= 0 ); 40 TEST_ASSERT( close( got_fd ) >= 0 ); 41 } 42 ctx->fd = wanted_fd; 43 return( 0 ); 44exit: 45 return( -1 ); 46} 47#endif /* MBEDTLS_PLATFORM_IS_UNIXLIKE */ 48 49/* END_HEADER */ 50 51/* BEGIN_DEPENDENCIES 52 * depends_on:MBEDTLS_NET_C 53 * END_DEPENDENCIES 54 */ 55 56/* BEGIN_CASE */ 57void context_init_free( int reinit ) 58{ 59 mbedtls_net_context ctx; 60 61 mbedtls_net_init( &ctx ); 62 mbedtls_net_free( &ctx ); 63 64 if( reinit ) 65 mbedtls_net_init( &ctx ); 66 mbedtls_net_free( &ctx ); 67 68 /* This test case always succeeds, functionally speaking. A plausible 69 * bug might trigger an invalid pointer dereference or a memory leak. */ 70 goto exit; 71} 72/* END_CASE */ 73 74/* BEGIN_CASE depends_on:MBEDTLS_PLATFORM_IS_UNIXLIKE */ 75void poll_beyond_fd_setsize( ) 76{ 77 /* Test that mbedtls_net_poll does not misbehave when given a file 78 * descriptor greater or equal to FD_SETSIZE. This code is specific to 79 * platforms with a Unix-like select() function, which is where 80 * FD_SETSIZE is a concern. */ 81 82 struct rlimit rlim_nofile; 83 int restore_rlim_nofile = 0; 84 int ret; 85 mbedtls_net_context ctx; 86 uint8_t buf[1]; 87 88 mbedtls_net_init( &ctx ); 89 90 /* On many systems, by default, the maximum permitted file descriptor 91 * number is less than FD_SETSIZE. If so, raise the limit if 92 * possible. 93 * 94 * If the limit can't be raised, a file descriptor opened by the 95 * net_sockets module will be less than FD_SETSIZE, so the test 96 * is not necessary and we mark it as skipped. 97 * A file descriptor could still be higher than FD_SETSIZE if it was 98 * opened before the limit was lowered (which is something an application 99 * might do); but we don't do such things in our test code, so the unit 100 * test will run if it can. 101 */ 102 TEST_ASSERT( getrlimit( RLIMIT_NOFILE, &rlim_nofile ) == 0 ); 103 if( rlim_nofile.rlim_cur < FD_SETSIZE + 1 ) 104 { 105 rlim_t old_rlim_cur = rlim_nofile.rlim_cur; 106 rlim_nofile.rlim_cur = FD_SETSIZE + 1; 107 TEST_ASSUME( setrlimit( RLIMIT_NOFILE, &rlim_nofile ) == 0 ); 108 rlim_nofile.rlim_cur = old_rlim_cur; 109 restore_rlim_nofile = 1; 110 } 111 112 TEST_ASSERT( open_file_on_fd( &ctx, FD_SETSIZE ) == 0 ); 113 114 /* In principle, mbedtls_net_poll() with valid arguments should succeed. 115 * However, we know that on Unix-like platforms (and others), this function 116 * is implemented on top of select() and fd_set, which do not support 117 * file descriptors greater or equal to FD_SETSIZE. So we expect to hit 118 * this platform limitation. 119 * 120 * If mbedtls_net_poll() does not proprely check that ctx.fd is in range, 121 * it may still happen to return the expected failure code, but if this 122 * is problematic on the particular platform where the code is running, 123 * a memory sanitizer such as UBSan should catch it. 124 */ 125 ret = mbedtls_net_poll( &ctx, MBEDTLS_NET_POLL_READ, 0 ); 126 TEST_EQUAL( ret, MBEDTLS_ERR_NET_POLL_FAILED ); 127 128 /* mbedtls_net_recv_timeout() uses select() and fd_set in the same way. */ 129 ret = mbedtls_net_recv_timeout( &ctx, buf, sizeof( buf ), 0 ); 130 TEST_EQUAL( ret, MBEDTLS_ERR_NET_POLL_FAILED ); 131 132exit: 133 mbedtls_net_free( &ctx ); 134 if( restore_rlim_nofile ) 135 setrlimit( RLIMIT_NOFILE, &rlim_nofile ); 136} 137/* END_CASE */ 138