diff --git a/core/utils.c b/core/utils.c index a250542d..f9222941 100644 --- a/core/utils.c +++ b/core/utils.c @@ -543,6 +543,26 @@ void uwsgi_as_root() { } } + if (uwsgi.refork_post_jail) { + uwsgi_log("re-fork()ing...\n"); + pid_t pid = fork(); + if (pid < 0) { + uwsgi_error("fork()"); + exit(1); + } + if (pid > 0) { + // block all signals + sigset_t smask; + sigfillset(&smask); + sigprocmask(SIG_BLOCK, &smask, NULL); + int status; + if (waitpid(pid, &status, 0) < 0) { + uwsgi_error("waitpid()"); + } + _exit(0); + } + } + int i; for (i = 0; i < uwsgi.gp_cnt; i++) { @@ -592,6 +612,26 @@ void uwsgi_as_root() { } #endif + if (uwsgi.refork_as_root) { + uwsgi_log("re-fork()ing...\n"); + pid_t pid = fork(); + if (pid < 0) { + uwsgi_error("fork()"); + exit(1); + } + if (pid > 0) { + // block all signals + sigset_t smask; + sigfillset(&smask); + sigprocmask(SIG_BLOCK, &smask, NULL); + int status; + if (waitpid(pid, &status, 0) < 0) { + uwsgi_error("waitpid()"); + } + _exit(0); + } + } + struct uwsgi_string_list *usl; uwsgi_foreach(usl, uwsgi.wait_for_interface) { diff --git a/core/uwsgi.c b/core/uwsgi.c index 3b6d8d2e..42fad6d4 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -320,6 +320,10 @@ static struct uwsgi_option uwsgi_base_options[] = { #endif {"refork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0}, {"re-fork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0}, + {"refork-as-root", no_argument, 0, "fork() again before privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_as_root, 0}, + {"re-fork-as-root", no_argument, 0, "fork() again before privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_as_root, 0}, + {"refork-post-jail", no_argument, 0, "fork() again after jailing. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_post_jail, 0}, + {"re-fork-post-jail", no_argument, 0, "fork() again after jailing. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_post_jail, 0}, {"hook-pre-jail", required_argument, 0, "run the specified hook before jailing", uwsgi_opt_add_string_list, &uwsgi.hook_pre_jail, 0}, {"hook-post-jail", required_argument, 0, "run the specified hook after jailing", uwsgi_opt_add_string_list, &uwsgi.hook_post_jail, 0}, diff --git a/plugins/tuntap/common.c b/plugins/tuntap/common.c index e8bf90e3..bd0ed158 100644 --- a/plugins/tuntap/common.c +++ b/plugins/tuntap/common.c @@ -68,16 +68,24 @@ struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_get_by_addr(uint32_t addr) { void uwsgi_tuntap_block_reads() { struct uwsgi_tuntap_peer *uttp = utt.peers_head; while (uttp) { - if (!uttp->wait_for_write) { - if (!uttp->blocked_read) { + if (!uttp->blocked_read) { + if (!uttp->wait_for_write) { if (event_queue_del_fd(utt.queue, uttp->fd, event_queue_read())) { struct uwsgi_tuntap_peer *tmp_uttp = uttp; uttp = uttp->next; uwsgi_tuntap_peer_destroy(tmp_uttp); continue; } - uttp->blocked_read = 1; } + else { + if (event_queue_fd_readwrite_to_write(utt.queue, uttp->fd)) { + struct uwsgi_tuntap_peer *tmp_uttp = uttp; + uttp = uttp->next; + uwsgi_tuntap_peer_destroy(tmp_uttp); + continue; + } + } + uttp->blocked_read = 1; } uttp = uttp->next; } @@ -88,11 +96,21 @@ void uwsgi_tuntap_unblock_reads() { struct uwsgi_tuntap_peer *uttp = utt.peers_head; while (uttp) { if (uttp->blocked_read) { - if (event_queue_add_fd_read(utt.queue, uttp->fd)) { - struct uwsgi_tuntap_peer *tmp_uttp = uttp; - uttp = uttp->next; - uwsgi_tuntap_peer_destroy(tmp_uttp); - continue; + if (!uttp->wait_for_write) { + if (event_queue_add_fd_read(utt.queue, uttp->fd)) { + struct uwsgi_tuntap_peer *tmp_uttp = uttp; + uttp = uttp->next; + uwsgi_tuntap_peer_destroy(tmp_uttp); + continue; + } + } + else { + if (event_queue_fd_write_to_readwrite(utt.queue, uttp->fd)) { + struct uwsgi_tuntap_peer *tmp_uttp = uttp; + uttp = uttp->next; + uwsgi_tuntap_peer_destroy(tmp_uttp); + continue; + } } uttp->blocked_read = 0; } @@ -155,6 +173,7 @@ int uwsgi_tuntap_peer_dequeue(struct uwsgi_tuntap_peer *uttp) { return -1; } uttp->buf_pos += rlen; + uttp->rx += rlen; // a whole pkt has been received if (uttp->buf_pos >= uttp->buf_pktsize) { @@ -204,6 +223,7 @@ int uwsgi_tuntap_peer_dequeue(struct uwsgi_tuntap_peer *uttp) { if (uttp->header_pos >= 4) { uint16_t *pktsize = (uint16_t *) &uttp->header[1]; uttp->buf_pktsize = *pktsize; + uttp->rx += 4; } return 0; } @@ -225,6 +245,7 @@ int uwsgi_tuntap_peer_enqueue(struct uwsgi_tuntap_peer *uttp) { } uttp->written += rlen; + uttp->tx += rlen; if (uttp->written >= uttp->write_buf_pktsize) { uttp->written = 0; uttp->write_buf_pktsize = 0; @@ -238,12 +259,12 @@ int uwsgi_tuntap_peer_enqueue(struct uwsgi_tuntap_peer *uttp) { } } else { - if (event_queue_fd_write_to_read(utt.queue, uttp->fd)) { + if (event_queue_fd_readwrite_to_read(utt.queue, uttp->fd)) { uwsgi_error("uwsgi_tuntap_peer_enqueue()/event_queue_fd_write_to_read()"); return -1; } } - utt.wait_for_write = 0; + uttp->wait_for_write = 0; } return 0; } @@ -253,7 +274,7 @@ int uwsgi_tuntap_peer_enqueue(struct uwsgi_tuntap_peer *uttp) { retry: if (!uttp->wait_for_write) { - if (event_queue_fd_read_to_write(utt.queue, uttp->fd)) { + if (event_queue_fd_read_to_readwrite(utt.queue, uttp->fd)) { uwsgi_error("uwsgi_tuntap_peer_enqueue()/event_queue_fd_read_to_write()"); return -1; } diff --git a/plugins/tuntap/common.h b/plugins/tuntap/common.h index 18ded607..dfd09e22 100644 --- a/plugins/tuntap/common.h +++ b/plugins/tuntap/common.h @@ -28,6 +28,10 @@ struct uwsgi_tuntap_peer { uint16_t write_buf_pos; struct uwsgi_tuntap_peer *prev; struct uwsgi_tuntap_peer *next; + // counters + uint64_t tx; + uint64_t rx; + uint64_t dropped; }; struct uwsgi_tuntap_firewall_rule { diff --git a/plugins/tuntap/tuntap.c b/plugins/tuntap/tuntap.c index b2f6f35a..4e4cc6e5 100644 --- a/plugins/tuntap/tuntap.c +++ b/plugins/tuntap/tuntap.c @@ -88,9 +88,15 @@ static void *uwsgi_tuntap_loop(void *arg) { event_queue_add_fd_read(utt.queue, fd); int server_fd = uwsgi_connect("/tmp/tuntap.socket", 30, 0); - if (event_queue_add_fd_read(utt.queue, server_fd)) { - // retry; + if (server_fd < 0) { + uwsgi_error("uwsgi_tuntap_loop()/uwsgi_connect()"); + exit(1); } + if (event_queue_add_fd_read(utt.queue, server_fd)) { + exit(1); + } + + uwsgi_socket_nb(server_fd); struct uwsgi_tuntap_peer *uttp = uwsgi_tuntap_peer_create(server_fd); @@ -137,8 +143,9 @@ static void *uwsgi_tuntap_loop(void *arg) { } else { // something is wrong (the tuntap device is blocked) - if (utt.wait_for_write) + if (utt.wait_for_write) { continue; + } // write to the client if (uwsgi_tuntap_peer_enqueue(uttp)) { @@ -197,7 +204,10 @@ void uwsgi_tuntap_router_loop(int id, void *foobar) { continue; // check for full write buffer - if (uttp->write_buf_pktsize + 4 + rlen > utt.buffer_size) continue; + if (uttp->write_buf_pktsize + 4 + rlen > utt.buffer_size) { + uttp->dropped++; + continue; + } uint16_t pktsize = rlen; char *ptr = uttp->write_buf + uttp->write_buf_pktsize; @@ -230,13 +240,14 @@ void uwsgi_tuntap_router_loop(int id, void *foobar) { while (uttp) { if (interesting_fd == uttp->fd) { // read from the client - if (!uttp->wait_for_write) { + if (event_queue_interesting_fd_is_read(events, i)) { if (uwsgi_tuntap_peer_dequeue(uttp)) { uwsgi_tuntap_peer_destroy(uttp); break; } } - else { + + if (event_queue_interesting_fd_is_write(events, i)) { // something is wrong (the tuntap device is blocked) if (utt.wait_for_write) break; diff --git a/uwsgi.h b/uwsgi.h index 476b2578..6b055da9 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1869,6 +1869,8 @@ struct uwsgi_server { char *jail_attach; #endif int refork; + int refork_as_root; + int refork_post_jail; int ignore_sigpipe; int ignore_write_errors;