blob: 2db79c59eae575001d0ddaa81c6be43f9721145c [file] [log] [blame]
Gilles Peskine1c0e48a2021-02-24 18:37:46 +01001/* BEGIN_HEADER */
2
3#include "mbedtls/net_sockets.h"
4
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +02005#if defined(unix) || defined(__unix__) || defined(__unix) || \
6 defined(__APPLE__) || defined(__QNXNTO__) || defined(__HAIKU__) || \
7 defined(__midipix__)
8# define MBEDTLS_PLATFORM_IS_UNIXLIKE
Gilles Peskine6667a782021-02-24 19:41:29 +01009#endif
10
11#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020012# include <sys/fcntl.h>
13# include <sys/resource.h>
14# include <sys/stat.h>
15# include <sys/time.h>
16# include <sys/types.h>
17# include <unistd.h>
Gilles Peskine6667a782021-02-24 19:41:29 +010018#endif
19
Gilles Peskine6667a782021-02-24 19:41:29 +010020#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
21/** Open a file on the given file descriptor.
22 *
23 * This is disruptive if there is already something open on that descriptor.
24 * Caller beware.
25 *
26 * \param ctx An initialized, but unopened socket context.
27 * On success, it refers to the opened file (\p wanted_fd).
28 * \param wanted_fd The desired file descriptor.
29 *
30 * \return \c 0 on succes, a negative error code on error.
31 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020032static int open_file_on_fd(mbedtls_net_context *ctx, int wanted_fd)
Gilles Peskine6667a782021-02-24 19:41:29 +010033{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020034 int got_fd = open("/dev/null", O_RDONLY);
35 TEST_ASSERT(got_fd >= 0);
36 if (got_fd != wanted_fd) {
37 TEST_ASSERT(dup2(got_fd, wanted_fd) >= 0);
38 TEST_ASSERT(close(got_fd) >= 0);
Gilles Peskine6667a782021-02-24 19:41:29 +010039 }
40 ctx->fd = wanted_fd;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020041 return 0;
Gilles Peskine6667a782021-02-24 19:41:29 +010042exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020043 return -1;
Gilles Peskine6667a782021-02-24 19:41:29 +010044}
45#endif /* MBEDTLS_PLATFORM_IS_UNIXLIKE */
46
Gilles Peskine1c0e48a2021-02-24 18:37:46 +010047/* END_HEADER */
48
49/* BEGIN_DEPENDENCIES
50 * depends_on:MBEDTLS_NET_C
51 * END_DEPENDENCIES
52 */
53
54/* BEGIN_CASE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020055void context_init_free(int reinit)
Gilles Peskine1c0e48a2021-02-24 18:37:46 +010056{
57 mbedtls_net_context ctx;
58
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020059 mbedtls_net_init(&ctx);
60 mbedtls_net_free(&ctx);
Gilles Peskine1c0e48a2021-02-24 18:37:46 +010061
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020062 if (reinit)
63 mbedtls_net_init(&ctx);
64 mbedtls_net_free(&ctx);
Gilles Peskine1c0e48a2021-02-24 18:37:46 +010065
66 /* This test case always succeeds, functionally speaking. A plausible
67 * bug might trigger an invalid pointer dereference or a memory leak. */
68 goto exit;
69}
70/* END_CASE */
Gilles Peskine6667a782021-02-24 19:41:29 +010071
72/* BEGIN_CASE depends_on:MBEDTLS_PLATFORM_IS_UNIXLIKE */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020073void poll_beyond_fd_setsize()
Gilles Peskine6667a782021-02-24 19:41:29 +010074{
75 /* Test that mbedtls_net_poll does not misbehave when given a file
Gilles Peskine97c57fe2021-03-01 11:40:56 +010076 * descriptor greater or equal to FD_SETSIZE. This code is specific to
77 * platforms with a Unix-like select() function, which is where
78 * FD_SETSIZE is a concern. */
Gilles Peskine6667a782021-02-24 19:41:29 +010079
80 struct rlimit rlim_nofile;
81 int restore_rlim_nofile = 0;
82 int ret;
83 mbedtls_net_context ctx;
84 uint8_t buf[1];
85
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020086 mbedtls_net_init(&ctx);
Gilles Peskine6667a782021-02-24 19:41:29 +010087
88 /* On many systems, by default, the maximum permitted file descriptor
Gilles Peskine97c57fe2021-03-01 11:40:56 +010089 * number is less than FD_SETSIZE. If so, raise the limit if
Gilles Peskine6667a782021-02-24 19:41:29 +010090 * possible.
91 *
Gilles Peskine97c57fe2021-03-01 11:40:56 +010092 * If the limit can't be raised, a file descriptor opened by the
93 * net_sockets module will be less than FD_SETSIZE, so the test
94 * is not necessary and we mark it as skipped.
Gilles Peskine574cf7b2021-03-01 11:43:22 +010095 * A file descriptor could still be higher than FD_SETSIZE if it was
96 * opened before the limit was lowered (which is something an application
97 * might do); but we don't do such things in our test code, so the unit
98 * test will run if it can.
Gilles Peskine6667a782021-02-24 19:41:29 +010099 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200100 TEST_ASSERT(getrlimit(RLIMIT_NOFILE, &rlim_nofile) == 0);
101 if (rlim_nofile.rlim_cur < FD_SETSIZE + 1) {
Gilles Peskine6667a782021-02-24 19:41:29 +0100102 rlim_t old_rlim_cur = rlim_nofile.rlim_cur;
103 rlim_nofile.rlim_cur = FD_SETSIZE + 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200104 TEST_ASSUME(setrlimit(RLIMIT_NOFILE, &rlim_nofile) == 0);
Gilles Peskine6667a782021-02-24 19:41:29 +0100105 rlim_nofile.rlim_cur = old_rlim_cur;
106 restore_rlim_nofile = 1;
107 }
108
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200109 TEST_ASSERT(open_file_on_fd(&ctx, FD_SETSIZE) == 0);
Gilles Peskine6667a782021-02-24 19:41:29 +0100110
111 /* In principle, mbedtls_net_poll() with valid arguments should succeed.
112 * However, we know that on Unix-like platforms (and others), this function
113 * is implemented on top of select() and fd_set, which do not support
Gilles Peskine97c57fe2021-03-01 11:40:56 +0100114 * file descriptors greater or equal to FD_SETSIZE. So we expect to hit
115 * this platform limitation.
Gilles Peskine6667a782021-02-24 19:41:29 +0100116 *
117 * If mbedtls_net_poll() does not proprely check that ctx.fd is in range,
118 * it may still happen to return the expected failure code, but if this
119 * is problematic on the particular platform where the code is running,
120 * a memory sanitizer such as UBSan should catch it.
121 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200122 ret = mbedtls_net_poll(&ctx, MBEDTLS_NET_POLL_READ, 0);
123 TEST_EQUAL(ret, MBEDTLS_ERR_NET_POLL_FAILED);
Gilles Peskine6667a782021-02-24 19:41:29 +0100124
125 /* mbedtls_net_recv_timeout() uses select() and fd_set in the same way. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200126 ret = mbedtls_net_recv_timeout(&ctx, buf, sizeof(buf), 0);
127 TEST_EQUAL(ret, MBEDTLS_ERR_NET_POLL_FAILED);
Gilles Peskine6667a782021-02-24 19:41:29 +0100128
129exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200130 mbedtls_net_free(&ctx);
131 if (restore_rlim_nofile)
132 setrlimit(RLIMIT_NOFILE, &rlim_nofile);
Gilles Peskine6667a782021-02-24 19:41:29 +0100133}
134/* END_CASE */