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