aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Timber <mieabby@gmail.com>2020-09-08 19:46:44 +0930
committerDavid Timber <mieabby@gmail.com>2020-09-08 20:10:57 +0930
commit0e512e6ae3146fcf3ce2427c8c36937d708d149b (patch)
tree40a6ad8c64b419e2f8d0bcc289e9608852ff76ae
parent550d2eec27a42254b26139208765022fffe7c775 (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.json4
-rw-r--r--proone.code-workspace2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/htbt.c19
-rw-r--r--src/mbedtls.c3
-rw-r--r--src/proone.c4
-rw-r--r--src/pth.c43
-rw-r--r--src/pth.h11
-rw-r--r--src/resolv.c4
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
diff --git a/src/htbt.c b/src/htbt.c
index 20fbe0f..3311893 100644
--- a/src/htbt.c
+++ b/src/htbt.c
@@ -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;
diff --git a/src/pth.c b/src/pth.c
index d82a465..2294c90 100644
--- a/src/pth.c
+++ b/src/pth.c
@@ -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));
diff --git a/src/pth.h b/src/pth.h
index 3b0d708..0ede191 100644
--- a/src/pth.h
+++ b/src/pth.h
@@ -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);