blob: 111a34950832dbead93eafb9653152c3043ba591 [file] [log] [blame]
Gilles Peskine1c0e48a2021-02-24 18:37:46 +01001/* BEGIN_HEADER */
2
3#include "mbedtls/net_sockets.h"
4
Gilles Peskine6667a782021-02-24 19:41:29 +01005#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/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>
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 succes, 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 {
39 TEST_ASSERT( dup2( got_fd, wanted_fd ) >= 0 );
40 TEST_ASSERT( close( got_fd ) >= 0 );
41 }
42 ctx->fd = wanted_fd;
43 return( 0 );
44exit:
45 return( -1 );
46}
47#endif /* MBEDTLS_PLATFORM_IS_UNIXLIKE */
48
Gilles Peskine1c0e48a2021-02-24 18:37:46 +010049/* END_HEADER */
50
51/* BEGIN_DEPENDENCIES
52 * depends_on:MBEDTLS_NET_C
53 * END_DEPENDENCIES
54 */
55
56/* BEGIN_CASE */
57void context_init_free( int reinit )
58{
59 mbedtls_net_context ctx;
60
61 mbedtls_net_init( &ctx );
62 mbedtls_net_free( &ctx );
63
64 if( reinit )
65 mbedtls_net_init( &ctx );
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 */
Gilles Peskine6667a782021-02-24 19:41:29 +010073
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
Gilles Peskine97c57fe2021-03-01 11:40:56 +010078 * 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. */
Gilles Peskine6667a782021-02-24 19:41:29 +010081
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
Gilles Peskine97c57fe2021-03-01 11:40:56 +010091 * number is less than FD_SETSIZE. If so, raise the limit if
Gilles Peskine6667a782021-02-24 19:41:29 +010092 * possible.
93 *
Gilles Peskine97c57fe2021-03-01 11:40:56 +010094 * 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.
Gilles Peskine6667a782021-02-24 19:41:29 +010097 */
98 TEST_ASSERT( getrlimit( RLIMIT_NOFILE, &rlim_nofile ) == 0 );
Gilles Peskine97c57fe2021-03-01 11:40:56 +010099 if( rlim_nofile.rlim_cur < FD_SETSIZE + 1 )
Gilles Peskine6667a782021-02-24 19:41:29 +0100100 {
101 rlim_t old_rlim_cur = rlim_nofile.rlim_cur;
102 rlim_nofile.rlim_cur = FD_SETSIZE + 1;
103 TEST_ASSUME( setrlimit( RLIMIT_NOFILE, &rlim_nofile ) == 0 );
104 rlim_nofile.rlim_cur = old_rlim_cur;
105 restore_rlim_nofile = 1;
106 }
107
108 TEST_ASSERT( open_file_on_fd( &ctx, FD_SETSIZE ) == 0 );
109
110 /* In principle, mbedtls_net_poll() with valid arguments should succeed.
111 * However, we know that on Unix-like platforms (and others), this function
112 * is implemented on top of select() and fd_set, which do not support
Gilles Peskine97c57fe2021-03-01 11:40:56 +0100113 * file descriptors greater or equal to FD_SETSIZE. So we expect to hit
114 * this platform limitation.
Gilles Peskine6667a782021-02-24 19:41:29 +0100115 *
116 * If mbedtls_net_poll() does not proprely check that ctx.fd is in range,
117 * it may still happen to return the expected failure code, but if this
118 * is problematic on the particular platform where the code is running,
119 * a memory sanitizer such as UBSan should catch it.
120 */
121 ret = mbedtls_net_poll( &ctx, MBEDTLS_NET_POLL_READ, 0 );
122 TEST_EQUAL( ret, MBEDTLS_ERR_NET_POLL_FAILED );
123
124 /* mbedtls_net_recv_timeout() uses select() and fd_set in the same way. */
125 ret = mbedtls_net_recv_timeout( &ctx, buf, sizeof( buf ), 0 );
126 TEST_EQUAL( ret, MBEDTLS_ERR_NET_POLL_FAILED );
127
128exit:
129 mbedtls_net_free( &ctx );
130 if( restore_rlim_nofile )
131 setrlimit( RLIMIT_NOFILE, &rlim_nofile );
132}
133/* END_CASE */