Browse Source

proxy: fix double-free on exit-side tcp error (re-entrant loopback)

topo_upd
Evgeny 2 months ago
parent
commit
f3679b07a1
  1. 12
      src/proxy/socks_proxy.c
  2. 17
      src/proxy/tcp_proxy_server.c

12
src/proxy/socks_proxy.c

@ -86,12 +86,6 @@ static void send_close(struct socks_proxy_conn* c) {
else { c->close_pending = 0; c->close_sent = 1; } else { c->close_pending = 0; c->close_sent = 1; }
} }
static void send_error(struct socks_proxy_conn* c) {
DEBUG_TRACE(DEBUG_CATEGORY_PROXY, "SOCKS send ERROR sid=%08x", c->stream_id);
if (send_msg(c->inst, TOPO_GROUP_UTUN, c->via_node_id, TCP_PROXY_SUBCMD_ERROR, c->stream_id, NULL, 0, 1) < 0) c->close_pending = 1;
else { c->close_pending = 0; c->close_sent = 1; }
}
static void send_fin(struct socks_proxy_conn* c) { static void send_fin(struct socks_proxy_conn* c) {
DEBUG_TRACE(DEBUG_CATEGORY_PROXY, "SOCKS send FIN sid=%08x", c->stream_id); DEBUG_TRACE(DEBUG_CATEGORY_PROXY, "SOCKS send FIN sid=%08x", c->stream_id);
send_msg(c->inst, TOPO_GROUP_UTUN, c->via_node_id, TCP_PROXY_SUBCMD_FIN, c->stream_id, NULL, 0, 1); send_msg(c->inst, TOPO_GROUP_UTUN, c->via_node_id, TCP_PROXY_SUBCMD_FIN, c->stream_id, NULL, 0, 1);
@ -440,8 +434,12 @@ static void on_error_cb(struct tcp_conn* tc, int err, void* arg) {
"bytes_client=%u bytes_exit=%u wq=%d", "bytes_client=%u bytes_exit=%u wq=%d",
c->stream_id, err, c->state, tc->fin_remote, tc->fin_local, c->rem_closed, c->close_sent, c->close_pending, c->stream_id, err, c->state, tc->fin_remote, tc->fin_local, c->rem_closed, c->close_sent, c->close_pending,
c->bytes_to_client, c->bytes_from_exit, c->tc->write_queue->count); c->bytes_to_client, c->bytes_from_exit, c->tc->write_queue->count);
if (!c->close_sent && !c->close_pending) send_error(c); int notify = !c->close_sent && !c->close_pending;
struct UTUN_INSTANCE* inst = c->inst;
uint64_t via = c->via_node_id;
uint32_t sid = c->stream_id;
socks_proxy_conn_free(c); socks_proxy_conn_free(c);
if (notify && inst) send_msg(inst, TOPO_GROUP_UTUN, via, TCP_PROXY_SUBCMD_ERROR, sid, NULL, 0, 1);
} }
static void on_closed_cb(struct tcp_conn* tc, void* arg) { static void on_closed_cb(struct tcp_conn* tc, void* arg) {

17
src/proxy/tcp_proxy_server.c

@ -40,7 +40,6 @@ static void retry_timer_cb(void* arg);
static int send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t subcmd, static int send_msg(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst, uint8_t subcmd,
uint32_t sid, const uint8_t* data, size_t len, int force); uint32_t sid, const uint8_t* data, size_t len, int force);
static void send_close(struct tcp_proxy_server_conn* rc); static void send_close(struct tcp_proxy_server_conn* rc);
static void send_error(struct tcp_proxy_server_conn* rc);
void tcp_proxy_server_conn_free(struct tcp_proxy_server_conn* rc); void tcp_proxy_server_conn_free(struct tcp_proxy_server_conn* rc);
static inline int write_pending(struct tcp_conn* tc) { static inline int write_pending(struct tcp_conn* tc) {
@ -96,17 +95,6 @@ static void send_close(struct tcp_proxy_server_conn* rc) {
} }
} }
static void send_error(struct tcp_proxy_server_conn* rc) {
struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL;
if (!inst) return;
if (send_msg(inst, TOPO_GROUP_UTUN, rc->peer_node_id, TCP_PROXY_SUBCMD_ERROR, rc->stream_id, NULL, 0, 1) < 0) {
rc->close_pending = 1;
rc->close_backoff = 50;
if (!rc->close_timer)
rc->close_timer = uasync_set_timeout(rc->ua, rc->close_backoff, rc, close_retry_cb, "tps_close_retry");
}
}
static void send_fin(struct tcp_proxy_server_conn* rc) { static void send_fin(struct tcp_proxy_server_conn* rc) {
struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL;
if (!inst) return; if (!inst) return;
@ -175,8 +163,11 @@ static void on_error_cb(struct tcp_conn* tc, int err, void* arg) {
rc->drain_count, rc->data_count, rc->drain_count, rc->data_count,
tc ? tc->read_queue->count : 0, tc ? tc->write_queue->count : 0, tc ? tc->read_queue->count : 0, tc ? tc->write_queue->count : 0,
tc && tc->write_buf ? "y" : "n", tc ? tc->connected : 0); tc && tc->write_buf ? "y" : "n", tc ? tc->connected : 0);
send_error(rc); struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL;
uint64_t peer = rc->peer_node_id;
uint32_t sid = rc->stream_id;
tcp_proxy_server_conn_free(rc); tcp_proxy_server_conn_free(rc);
if (inst) send_msg(inst, TOPO_GROUP_UTUN, peer, TCP_PROXY_SUBCMD_ERROR, sid, NULL, 0, 1);
} }
static void diag_timer_cb(void* arg) { static void diag_timer_cb(void* arg) {

Loading…
Cancel
Save