blob: fa09f5a64f80fa84c998d3d8c2836f74a9af48cb [file] [log] [blame]
Tom Rini0344c602024-10-08 13:56:50 -06001/* 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 success, 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 TEST_ASSERT(dup2(got_fd, wanted_fd) >= 0);
39 TEST_ASSERT(close(got_fd) >= 0);
40 }
41 ctx->fd = wanted_fd;
42 return 0;
43exit:
44 return -1;
45}
46#endif /* MBEDTLS_PLATFORM_IS_UNIXLIKE */
47
48/* END_HEADER */
49
50/* BEGIN_DEPENDENCIES
51 * depends_on:MBEDTLS_NET_C
52 * END_DEPENDENCIES
53 */
54
55/* BEGIN_CASE */
56void context_init_free(int reinit)
57{
58 mbedtls_net_context ctx;
59
60 mbedtls_net_init(&ctx);
61 mbedtls_net_free(&ctx);
62
63 if (reinit) {
64 mbedtls_net_init(&ctx);
65 }
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 rlim_t old_rlim_cur = rlim_nofile.rlim_cur;
105 rlim_nofile.rlim_cur = FD_SETSIZE + 1;
106 TEST_ASSUME(setrlimit(RLIMIT_NOFILE, &rlim_nofile) == 0);
107 rlim_nofile.rlim_cur = old_rlim_cur;
108 restore_rlim_nofile = 1;
109 }
110
111 TEST_ASSERT(open_file_on_fd(&ctx, FD_SETSIZE) == 0);
112
113 /* In principle, mbedtls_net_poll() with valid arguments should succeed.
114 * However, we know that on Unix-like platforms (and others), this function
115 * is implemented on top of select() and fd_set, which do not support
116 * file descriptors greater or equal to FD_SETSIZE. So we expect to hit
117 * this platform limitation.
118 *
119 * If mbedtls_net_poll() does not proprely check that ctx.fd is in range,
120 * it may still happen to return the expected failure code, but if this
121 * is problematic on the particular platform where the code is running,
122 * a memory sanitizer such as UBSan should catch it.
123 */
124 ret = mbedtls_net_poll(&ctx, MBEDTLS_NET_POLL_READ, 0);
125 TEST_EQUAL(ret, MBEDTLS_ERR_NET_POLL_FAILED);
126
127 /* mbedtls_net_recv_timeout() uses select() and fd_set in the same way. */
128 ret = mbedtls_net_recv_timeout(&ctx, buf, sizeof(buf), 0);
129 TEST_EQUAL(ret, MBEDTLS_ERR_NET_POLL_FAILED);
130
131exit:
132 mbedtls_net_free(&ctx);
133 if (restore_rlim_nofile) {
134 setrlimit(RLIMIT_NOFILE, &rlim_nofile);
135 }
136}
137/* END_CASE */