| Gilles Peskine | 1c0e48a | 2021-02-24 18:37:46 +0100 | [diff] [blame] | 1 | /* BEGIN_HEADER */ | 
|  | 2 |  | 
|  | 3 | #include "mbedtls/net_sockets.h" | 
|  | 4 |  | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 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) | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 12 | #include <sys/resource.h> | 
|  | 13 | #include <sys/stat.h> | 
|  | 14 | #include <sys/time.h> | 
|  | 15 | #include <sys/types.h> | 
| joseph | 6113af6 | 2021-09-23 20:58:45 +0900 | [diff] [blame] | 16 | #include <fcntl.h> | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 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 | * | 
| Shaun Case | 8b0ecbc | 2021-12-20 21:14:10 -0800 | [diff] [blame] | 31 | * \return              \c 0 on success, a negative error code on error. | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 32 | */ | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 33 | static int open_file_on_fd(mbedtls_net_context *ctx, int wanted_fd) | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 34 | { | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 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); | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 40 | } | 
|  | 41 | ctx->fd = wanted_fd; | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 42 | return 0; | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 43 | exit: | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 44 | return -1; | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 45 | } | 
|  | 46 | #endif /* MBEDTLS_PLATFORM_IS_UNIXLIKE */ | 
|  | 47 |  | 
| Gilles Peskine | 1c0e48a | 2021-02-24 18:37:46 +0100 | [diff] [blame] | 48 | /* END_HEADER */ | 
|  | 49 |  | 
|  | 50 | /* BEGIN_DEPENDENCIES | 
|  | 51 | * depends_on:MBEDTLS_NET_C | 
|  | 52 | * END_DEPENDENCIES | 
|  | 53 | */ | 
|  | 54 |  | 
|  | 55 | /* BEGIN_CASE */ | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 56 | void context_init_free(int reinit) | 
| Gilles Peskine | 1c0e48a | 2021-02-24 18:37:46 +0100 | [diff] [blame] | 57 | { | 
|  | 58 | mbedtls_net_context ctx; | 
|  | 59 |  | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 60 | mbedtls_net_init(&ctx); | 
|  | 61 | mbedtls_net_free(&ctx); | 
| Gilles Peskine | 1c0e48a | 2021-02-24 18:37:46 +0100 | [diff] [blame] | 62 |  | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 63 | if (reinit) { | 
|  | 64 | mbedtls_net_init(&ctx); | 
|  | 65 | } | 
|  | 66 | mbedtls_net_free(&ctx); | 
| Gilles Peskine | 1c0e48a | 2021-02-24 18:37:46 +0100 | [diff] [blame] | 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 Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 73 |  | 
|  | 74 | /* BEGIN_CASE depends_on:MBEDTLS_PLATFORM_IS_UNIXLIKE */ | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 75 | void poll_beyond_fd_setsize() | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 76 | { | 
|  | 77 | /* Test that mbedtls_net_poll does not misbehave when given a file | 
| Gilles Peskine | 97c57fe | 2021-03-01 11:40:56 +0100 | [diff] [blame] | 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. */ | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 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 |  | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 88 | mbedtls_net_init(&ctx); | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 89 |  | 
|  | 90 | /* On many systems, by default, the maximum permitted file descriptor | 
| Gilles Peskine | 97c57fe | 2021-03-01 11:40:56 +0100 | [diff] [blame] | 91 | * number is less than FD_SETSIZE. If so, raise the limit if | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 92 | * possible. | 
|  | 93 | * | 
| Gilles Peskine | 97c57fe | 2021-03-01 11:40:56 +0100 | [diff] [blame] | 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. | 
| Gilles Peskine | 574cf7b | 2021-03-01 11:43:22 +0100 | [diff] [blame] | 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. | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 101 | */ | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 102 | TEST_ASSERT(getrlimit(RLIMIT_NOFILE, &rlim_nofile) == 0); | 
|  | 103 | if (rlim_nofile.rlim_cur < FD_SETSIZE + 1) { | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 104 | rlim_t old_rlim_cur = rlim_nofile.rlim_cur; | 
|  | 105 | rlim_nofile.rlim_cur = FD_SETSIZE + 1; | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 106 | TEST_ASSUME(setrlimit(RLIMIT_NOFILE, &rlim_nofile) == 0); | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 107 | rlim_nofile.rlim_cur = old_rlim_cur; | 
|  | 108 | restore_rlim_nofile = 1; | 
|  | 109 | } | 
|  | 110 |  | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 111 | TEST_ASSERT(open_file_on_fd(&ctx, FD_SETSIZE) == 0); | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 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 | 
| Gilles Peskine | 97c57fe | 2021-03-01 11:40:56 +0100 | [diff] [blame] | 116 | * file descriptors greater or equal to FD_SETSIZE. So we expect to hit | 
|  | 117 | * this platform limitation. | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 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 | */ | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 124 | ret = mbedtls_net_poll(&ctx, MBEDTLS_NET_POLL_READ, 0); | 
|  | 125 | TEST_EQUAL(ret, MBEDTLS_ERR_NET_POLL_FAILED); | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 126 |  | 
|  | 127 | /* mbedtls_net_recv_timeout() uses select() and fd_set in the same way. */ | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 128 | ret = mbedtls_net_recv_timeout(&ctx, buf, sizeof(buf), 0); | 
|  | 129 | TEST_EQUAL(ret, MBEDTLS_ERR_NET_POLL_FAILED); | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 130 |  | 
|  | 131 | exit: | 
| Gilles Peskine | 449bd83 | 2023-01-11 14:50:10 +0100 | [diff] [blame] | 132 | mbedtls_net_free(&ctx); | 
|  | 133 | if (restore_rlim_nofile) { | 
|  | 134 | setrlimit(RLIMIT_NOFILE, &rlim_nofile); | 
|  | 135 | } | 
| Gilles Peskine | 6667a78 | 2021-02-24 19:41:29 +0100 | [diff] [blame] | 136 | } | 
|  | 137 | /* END_CASE */ |