449bd8303e
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
137 lines
4.3 KiB
C
137 lines
4.3 KiB
C
/* 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 <sys/resource.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#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 success, 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 */
|