diff options
author | David Timber <mieabby@gmail.com> | 2020-09-08 19:46:44 +0930 |
---|---|---|
committer | David Timber <mieabby@gmail.com> | 2020-09-08 20:10:57 +0930 |
commit | 0e512e6ae3146fcf3ce2427c8c36937d708d149b (patch) | |
tree | 40a6ad8c64b419e2f8d0bcc289e9608852ff76ae | |
parent | 550d2eec27a42254b26139208765022fffe7c775 (diff) |
* Fix bug in pth_poll: wrong use of FD_SET()
causing undefined behaviour
* Fix bug in proone: loading ns pool from dvault for resolv
* Fix bug in htbt: improper handling of stream in htbt_relay_child()
* Switch back to _POSIX_C_SOURCE=200112L
-rw-r--r-- | .vscode/launch.json | 4 | ||||
-rw-r--r-- | proone.code-workspace | 2 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/htbt.c | 19 | ||||
-rw-r--r-- | src/mbedtls.c | 3 | ||||
-rw-r--r-- | src/proone.c | 4 | ||||
-rw-r--r-- | src/pth.c | 43 | ||||
-rw-r--r-- | src/pth.h | 11 | ||||
-rw-r--r-- | src/resolv.c | 4 |
9 files changed, 74 insertions, 18 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json index d0aa1f9..acc9e6b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -86,8 +86,8 @@ "MIMode": "gdb", "setupCommands": [ { - "description": "Follow parent fork", - "text": "set follow-fork-mode parent", + "description": "Follow child fork", + "text": "set follow-fork-mode child", "ignoreFailures": false }, { diff --git a/proone.code-workspace b/proone.code-workspace index 3464962..db33ae8 100644 --- a/proone.code-workspace +++ b/proone.code-workspace @@ -10,7 +10,7 @@ "files.trimTrailingWhitespace": true, "C_Cpp.default.cStandard": "c11", "C_Cpp.default.defines": [ - "_POSIX_C_SOURCE=199506L", + "_POSIX_C_SOURCE=200112L", "PRNE_DEBUG", "PRNE_BUILD_ENTROPY={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }", "PRNE_BIN_ALIGNMENT=8"], diff --git a/src/Makefile.am b/src/Makefile.am index e138e87..8b6369d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ BIN_ALIGNMENT = 8 -AM_CFLAGS = -std=c11 -pedantic -Wall -Wextra -Wno-switch -D_POSIX_C_SOURCE=199506L -Wno-unused-parameter -DPRNE_BIN_ALIGNMENT=$(BIN_ALIGNMENT) -fdata-sections -ffunction-sections -Wl,--gc-sections +AM_CFLAGS = -std=c11 -pedantic -Wall -Wextra -Wno-switch -D_POSIX_C_SOURCE=200112L -Wno-unused-parameter -DPRNE_BIN_ALIGNMENT=$(BIN_ALIGNMENT) -fdata-sections -ffunction-sections -Wl,--gc-sections if DEBUG AM_CFLAGS += -g -O0 -DPRNE_DEBUG else @@ -352,7 +352,7 @@ static prne_htbt_status_code_t htbt_relay_child ( * Await cv if you want to terminate the connection right away * when the program is terminating. */ - f_ret = pth_poll_ev(pfd, 5, -1, ev); + f_ret = prne_pth_poll(pfd, 5, -1, ev); if (f_ret < 0 && errno != EINTR) { ret = PRNE_HTBT_STATUS_ERRNO; break; @@ -392,6 +392,13 @@ static prne_htbt_status_code_t htbt_relay_child ( consume += actual; prne_iobuf_shift(ctx->iobuf + 0, -consume); } while (false); + + if (sh[0].len == 0 && pfd[0].fd < 0) { + // There's still pending stdin data and EOF. + // This is proto err. + ret = PRNE_HTBT_STATUS_PROTO_ERR; + break; + } } if (pfd[0].revents) { @@ -401,12 +408,6 @@ static prne_htbt_status_code_t htbt_relay_child ( ctx->iobuf[0].avail); if (f_ret == 0) { pfd[0].fd = -1; - if (sh[0].len > 0) { - // There's still pending stdin data and EOF. - // This is proto err. - ret = PRNE_HTBT_STATUS_PROTO_ERR; - break; - } } else if (f_ret < 0) { ctx->valid = false; @@ -765,7 +766,7 @@ static void htbt_slv_consume_outbuf ( pfd.events = POLLOUT; while (ctx->valid && ctx->iobuf[1].len > 0) { - fret = pth_poll_ev(&pfd, 1, -1, root_ev); + fret = prne_pth_poll(&pfd, 1, -1, root_ev); if (root_ev != NULL && pth_event_status(root_ev) != PTH_STATUS_PENDING) { @@ -1098,7 +1099,7 @@ static bool htbt_slv_srv_bin ( prne_assert(ev != NULL); if (ctx->iobuf[0].len == 0) { - f_ret = pth_poll_ev(&pfd, 1, -1, ev); + f_ret = prne_pth_poll(&pfd, 1, -1, ev); if (pth_event_status(ev) == PTH_STATUS_OCCURRED || f_ret == 0) { diff --git a/src/mbedtls.c b/src/mbedtls.c index 3b1c49f..65d2685 100644 --- a/src/mbedtls.c +++ b/src/mbedtls.c @@ -1,6 +1,7 @@ #include "mbedtls.h" #include "util_ct.h" #include "util_rt.h" +#include "pth.h" #include <errno.h> #include <string.h> @@ -139,7 +140,7 @@ bool prne_mbedtls_pth_handle ( } do { - pollret = pth_poll_ev(&pfd, 1, -1, ev); + pollret = prne_pth_poll(&pfd, 1, -1, ev); if (pollret < 0) { if (errno == EINTR) { continue; diff --git a/src/proone.c b/src/proone.c index 5e40796..623d3b6 100644 --- a/src/proone.c +++ b/src/proone.c @@ -47,7 +47,7 @@ static void alloc_resolv (void) { bin = prne_dvault_get_bin(PRNE_DATA_KEY_RESOLV_NS_IPV4, &len); prne_dbgast(len != 0 && len % 16 == 0); - cnt = len * 16; + cnt = len / 16; if (!prne_resolv_alloc_ns_pool(&pool4, cnt)) { goto END; @@ -60,7 +60,7 @@ static void alloc_resolv (void) { bin = prne_dvault_get_bin(PRNE_DATA_KEY_RESOLV_NS_IPV6, &len); prne_dbgast(len != 0 && len % 16 == 0); - cnt = len * 16; + cnt = len / 16; if (!prne_resolv_alloc_ns_pool(&pool6, cnt)) { goto END; @@ -26,6 +26,49 @@ void prne_fin_worker (prne_worker_t *w) { } } +int prne_pth_poll ( + struct pollfd *pfd, + const nfds_t nfs, + const int timeout, + pth_event_t ev) +{ + struct pollfd my_pfd[nfs]; + nfds_t p; + int ret; + + p = 0; + for (nfds_t i = 0; i < nfs; i += 1) { + if (pfd[i].fd >= FD_SETSIZE) { + errno = EINVAL; + return -1; + } + if (0 <= pfd[i].fd) { + my_pfd[p].fd = pfd[i].fd; + my_pfd[p].events = pfd[i].events; + p += 1; + } + } + if (p == 0) { + return 0; + } + + ret = pth_poll_ev(my_pfd, p, timeout, ev); + if (ret >= 0) { + p = 0; + for (nfds_t i = 0; i < nfs; i += 1) { + if (0 <= pfd[i].fd) { + pfd[i].revents = my_pfd[p].revents; + p += 1; + } + else { + pfd[i].revents = 0; + } + } + } + + return ret; +} + void prne_pth_cv_notify (pth_mutex_t *lock, pth_cond_t *cond, bool broadcast) { prne_dbgtrap(pth_mutex_acquire(lock, FALSE, NULL)); prne_dbgtrap(pth_cond_notify(cond, broadcast)); @@ -25,5 +25,16 @@ void prne_init_worker (prne_worker_t *w); void prne_free_worker (prne_worker_t *w); void prne_fin_worker (prne_worker_t *w); +/* Workaround for bug in GNU Pth +* Calling pth_poll() with pollfd element whose fd is negative value results in +* undefined behaviour as stated in POSIX(FD_SET() with invalid value is +* undefined). GNU Pth uses FD_SET() with invalid values on purpose to achieve +* something. +*/ +int prne_pth_poll ( + struct pollfd *pfd, + const nfds_t nfs, + const int timeout, + pth_event_t ev); void prne_pth_cv_notify (pth_mutex_t *lock, pth_cond_t *cond, bool broadcast); pth_time_t prne_pth_tstimeout (const struct timespec ts); diff --git a/src/resolv.c b/src/resolv.c index 1fb04fa..30fbac6 100644 --- a/src/resolv.c +++ b/src/resolv.c @@ -426,7 +426,7 @@ static bool resolv_ensure_act_dns_fd (prne_resolv_t *ctx) { while (pfs[0].fd >= 0 || pfs[1].fd >= 0) { pth_status_t st; - pollret = pth_poll_ev(pfs, 2, -1, ev); + pollret = prne_pth_poll(pfs, 2, -1, ev); st = pth_event_status(ev); if (st == PTH_STATUS_OCCURRED) { @@ -1077,7 +1077,7 @@ LOOP: ctx->act_sck_pfd.events = pfd_events; prne_assert(ev != NULL); // fatal without timeout - pollret = pth_poll_ev(&ctx->act_sck_pfd, 1, -1, ev); + pollret = prne_pth_poll(&ctx->act_sck_pfd, 1, -1, ev); if (pth_event_status(ev) != PTH_STATUS_PENDING) { resolv_close_sck(ctx, NULL, true); |