/* BEGIN_HEADER */ #include "mbedtls/net_sockets.h" #if defined(unix) || defined(__unix__) || defined(__unix) || \ defined(__APPLE__) || defined(__QNXNTO__) || \ defined(__HAIKU__) || defined(__midipix__) #define MBEDTLS_PLATFORM_IS_UNIXLIKE #endif #if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE) #include #include #include #include #include #include #endif #if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE) /** Open a file on the given file descriptor. * * This is disruptive if there is already something open on that descriptor. * Caller beware. * * \param ctx An initialized, but unopened socket context. * On success, it refers to the opened file (\p wanted_fd). * \param wanted_fd The desired file descriptor. * * \return \c 0 on succes, a negative error code on error. */ static int open_file_on_fd( mbedtls_net_context *ctx, int wanted_fd ) { int got_fd = open( "/dev/null", O_RDONLY ); TEST_ASSERT( got_fd >= 0 ); if( got_fd != wanted_fd ) { TEST_ASSERT( dup2( got_fd, wanted_fd ) >= 0 ); TEST_ASSERT( close( got_fd ) >= 0 ); } ctx->fd = wanted_fd; return( 0 ); exit: return( -1 ); } #endif /* MBEDTLS_PLATFORM_IS_UNIXLIKE */ /* END_HEADER */ /* BEGIN_DEPENDENCIES * depends_on:MBEDTLS_NET_C * END_DEPENDENCIES */ /* BEGIN_CASE */ void context_init_free( int reinit ) { mbedtls_net_context ctx; mbedtls_net_init( &ctx ); mbedtls_net_free( &ctx ); if( reinit ) mbedtls_net_init( &ctx ); mbedtls_net_free( &ctx ); /* This test case always succeeds, functionally speaking. A plausible * bug might trigger an invalid pointer dereference or a memory leak. */ goto exit; } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_PLATFORM_IS_UNIXLIKE */ void poll_beyond_fd_setsize( ) { /* Test that mbedtls_net_poll does not misbehave when given a file * descriptor greater or equal to FD_SETSIZE. This code is specific to * platforms with a Unix-like select() function, which is where * FD_SETSIZE is a concern. */ struct rlimit rlim_nofile; int restore_rlim_nofile = 0; int ret; mbedtls_net_context ctx; uint8_t buf[1]; mbedtls_net_init( &ctx ); /* On many systems, by default, the maximum permitted file descriptor * number is less than FD_SETSIZE. If so, raise the limit if * possible. * * If the limit can't be raised, a file descriptor opened by the * net_sockets module will be less than FD_SETSIZE, so the test * is not necessary and we mark it as skipped. * A file descriptor could still be higher than FD_SETSIZE if it was * opened before the limit was lowered (which is something an application * might do); but we don't do such things in our test code, so the unit * test will run if it can. */ TEST_ASSERT( getrlimit( RLIMIT_NOFILE, &rlim_nofile ) == 0 ); if( rlim_nofile.rlim_cur < FD_SETSIZE + 1 ) { rlim_t old_rlim_cur = rlim_nofile.rlim_cur; rlim_nofile.rlim_cur = FD_SETSIZE + 1; TEST_ASSUME( setrlimit( RLIMIT_NOFILE, &rlim_nofile ) == 0 ); rlim_nofile.rlim_cur = old_rlim_cur; restore_rlim_nofile = 1; } TEST_ASSERT( open_file_on_fd( &ctx, FD_SETSIZE ) == 0 ); /* In principle, mbedtls_net_poll() with valid arguments should succeed. * However, we know that on Unix-like platforms (and others), this function * is implemented on top of select() and fd_set, which do not support * file descriptors greater or equal to FD_SETSIZE. So we expect to hit * this platform limitation. * * If mbedtls_net_poll() does not proprely check that ctx.fd is in range, * it may still happen to return the expected failure code, but if this * is problematic on the particular platform where the code is running, * a memory sanitizer such as UBSan should catch it. */ ret = mbedtls_net_poll( &ctx, MBEDTLS_NET_POLL_READ, 0 ); TEST_EQUAL( ret, MBEDTLS_ERR_NET_POLL_FAILED ); /* mbedtls_net_recv_timeout() uses select() and fd_set in the same way. */ ret = mbedtls_net_recv_timeout( &ctx, buf, sizeof( buf ), 0 ); TEST_EQUAL( ret, MBEDTLS_ERR_NET_POLL_FAILED ); exit: mbedtls_net_free( &ctx ); if( restore_rlim_nofile ) setrlimit( RLIMIT_NOFILE, &rlim_nofile ); } /* END_CASE */