socks_proxy: defer conn free to fix UAF from synchronous write_queue flush
This commit is contained in:
1 parent
b085715654
commit
21ec740d82
2 files changed
+19
-4
No files matched your search
+18
-4
@@ -28,6 +28,8 @@ static void on_read_cb(struct ll_queue* q, void* arg);
|
||||
static void on_fin_cb(struct tcp_conn* tc, void* arg);
|
||||
static void on_error_cb(struct tcp_conn* tc, int err, void* arg);
|
||||
static void on_closed_cb(struct tcp_conn* tc, void* arg);
|
||||
static void socks_proxy_conn_free_deferred(void* arg);
|
||||
static void socks_proxy_conn_free_soon(struct socks_proxy_conn* c);
|
||||
static void tx_waiter_cb(struct ll_queue* q, void* arg);
|
||||
static void tx_retry_timer_cb(void* arg);
|
||||
static void socks_issue_dns(struct socks_proxy_conn* c, const char* host, uint8_t kind);
|
||||
@@ -119,8 +121,8 @@ static int write_to_client(struct socks_proxy_conn* c, const uint8_t* data, uint
|
||||
}
|
||||
memcpy(buf, data, len);
|
||||
e->dgram = buf; e->len = len;
|
||||
queue_data_put(c->tc->write_queue, e);
|
||||
c->bytes_to_client += len;
|
||||
queue_data_put(c->tc->write_queue, e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -556,7 +558,7 @@ static void on_error_cb(struct tcp_conn* tc, int err, void* arg) {
|
||||
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_soon(c);
|
||||
if (notify && inst) send_msg(inst, TOPO_GROUP_UTUN, via, TCP_PROXY_SUBCMD_ERROR, sid, NULL, 0, 1);
|
||||
}
|
||||
|
||||
@@ -565,7 +567,7 @@ static void on_closed_cb(struct tcp_conn* tc, void* arg) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_PROXY, "socks_proxy: tcp closed sid=%08x state=%d fm_r=%d fm_l=%d rem_cl=%d bytes_client=%u bytes_exit=%u",
|
||||
c->stream_id, c->state, tc->fin_remote, tc->fin_local, c->rem_closed, c->bytes_to_client, c->bytes_from_exit);
|
||||
if (!c->close_sent && !c->close_pending) send_close(c);
|
||||
socks_proxy_conn_free(c);
|
||||
socks_proxy_conn_free_soon(c);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
@@ -627,8 +629,8 @@ int socks_proxy_handle_etcp(struct socks_proxy_conn** head, int* count,
|
||||
uint8_t* buf = memory_pool_alloc(c->tc->data_pool);
|
||||
if (e && buf) {
|
||||
memcpy(buf, data, data_len); e->dgram = buf; e->len = (uint16_t)data_len;
|
||||
queue_data_put(c->tc->write_queue, e);
|
||||
c->bytes_to_client += (uint32_t)data_len;
|
||||
queue_data_put(c->tc->write_queue, e);
|
||||
} else {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "socks_proxy: handle_data alloc failed sid=%08x wq=%d bytes_in=%u bytes_out=%u",
|
||||
stream_id, c->tc->write_queue->count, c->bytes_from_exit, c->bytes_to_client);
|
||||
@@ -665,10 +667,22 @@ int socks_proxy_handle_etcp(struct socks_proxy_conn** head, int* count,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void socks_proxy_conn_free_deferred(void* arg) {
|
||||
struct socks_proxy_conn* c = (struct socks_proxy_conn*)arg;
|
||||
c->free_soon_id = NULL;
|
||||
socks_proxy_conn_free(c);
|
||||
}
|
||||
|
||||
static void socks_proxy_conn_free_soon(struct socks_proxy_conn* c) {
|
||||
if (!c || c->free_soon_id) return;
|
||||
c->free_soon_id = uasync_call_soon(c->ua, c, socks_proxy_conn_free_deferred);
|
||||
}
|
||||
|
||||
void socks_proxy_conn_free(struct socks_proxy_conn* c) {
|
||||
if (!c) return;
|
||||
if (c->freed) return;
|
||||
c->freed = 1;
|
||||
if (c->free_soon_id) { uasync_call_soon_cancel(c->ua, c->free_soon_id); c->free_soon_id = NULL; }
|
||||
struct socks_proxy_conn** head = c->head; int* count = c->count;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_PROXY, "socks_proxy: FREE sid=%08x state=%d total=%d", c->stream_id, c->state, count ? *count : 0);
|
||||
if (c->close_pending && c->inst) {
|
||||
|
||||
@@ -52,6 +52,7 @@ struct socks_proxy_conn {
|
||||
uint8_t is_http;
|
||||
uint8_t state;
|
||||
uint8_t freed;
|
||||
void* free_soon_id; // handle отложенного освобождения (uasync_call_soon)
|
||||
uint8_t buf[1024];
|
||||
uint16_t buf_len;
|
||||
uint8_t* tx_buf; // буфер при backpressure (retry в tx_waiter_cb)
|
||||
|
||||
Reference in new issue
Block a user