From a2edecfbad4774628c7a0cdddba6e9b43816986d Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Thu, 26 Mar 2026 20:46:54 +0300 Subject: [PATCH] Fix potential use-after-free on filters, add SSL_shutdown in SSLPlugin --- src/common.c | 1 + src/plugins/SSLPlugin/ssl_plugin.c | 11 +++++++-- src/proxymain.c | 36 +++++++++++++++--------------- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/common.c b/src/common.c index 8f8a55f..b6c9cdf 100644 --- a/src/common.c +++ b/src/common.c @@ -251,6 +251,7 @@ int return shutdown(s, how); } int WINAPI def_closesocket(void* state, SOCKET s){ + usleep(SLEEPTIME); return closesocket(s); } #else diff --git a/src/plugins/SSLPlugin/ssl_plugin.c b/src/plugins/SSLPlugin/ssl_plugin.c index f197af6..d390c3a 100644 --- a/src/plugins/SSLPlugin/ssl_plugin.c +++ b/src/plugins/SSLPlugin/ssl_plugin.c @@ -110,11 +110,13 @@ static void addSSL( void delSSL(void *state, SOCKET s){ if(!state || s == INVALID_SOCKET) return; if(STATE->cli.s == s) { + SSL_shutdown(STATE->cli.conn); ssl_conn_free(STATE->cli.conn); STATE->cli.conn = NULL; STATE->cli.s = INVALID_SOCKET; } else if(STATE->srv.s == s) { + SSL_shutdown(STATE->srv.conn); ssl_conn_free(STATE->srv.conn); STATE->srv.conn = NULL; STATE->srv.s = INVALID_SOCKET; @@ -630,8 +632,13 @@ static FILTER_ACTION ssl_filter_predata(void *fc, struct clientparam * param){ } -static void ssl_filter_clear(void *fc){ - free(fc); +static void ssl_filter_clear(void *state){ + struct clientparam *param; + + if(!state) return; + param = STATE->param; + free(state); + param->sostate = NULL; } #define CONFIG ((SSL_CONFIG *)fo) diff --git a/src/proxymain.c b/src/proxymain.c index 78a027d..95f8b1c 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -1072,24 +1072,6 @@ void srvfree(struct srvparam * srv){ void freeparam(struct clientparam * param) { if(param->res == 2) return; - if(param->datfilterssrv) myfree(param->datfilterssrv); -#ifndef STDMAIN - if(param->reqfilters) myfree(param->reqfilters); - if(param->connectfilters) myfree(param->connectfilters); - if(param->afterauthfilters) myfree(param->afterauthfilters); - if(param->hdrfilterscli) myfree(param->hdrfilterscli); - if(param->hdrfilterssrv) myfree(param->hdrfilterssrv); - if(param->predatfilters) myfree(param->predatfilters); - if(param->datfilterscli) myfree(param->datfilterscli); - if(param->filters){ - if(param->nfilters)while(param->nfilters--){ - if(param->filters[param->nfilters].filter->filter_clear) - (*param->filters[param->nfilters].filter->filter_clear)(param->filters[param->nfilters].data); - } - myfree(param->filters); - } - if(param->connlim) stopconnlims(param); -#endif if(param->clibuf) myfree(param->clibuf); if(param->srvbuf) myfree(param->srvbuf); if(param->ctrlsocksrv != INVALID_SOCKET && param->ctrlsocksrv != param->remsock) { @@ -1108,6 +1090,24 @@ void freeparam(struct clientparam * param) { param->srv->so._shutdown(param->sostate, param->clisock, SHUT_RDWR); param->srv->so._closesocket(param->sostate, param->clisock); } + if(param->datfilterssrv) myfree(param->datfilterssrv); +#ifndef STDMAIN + if(param->reqfilters) myfree(param->reqfilters); + if(param->connectfilters) myfree(param->connectfilters); + if(param->afterauthfilters) myfree(param->afterauthfilters); + if(param->hdrfilterscli) myfree(param->hdrfilterscli); + if(param->hdrfilterssrv) myfree(param->hdrfilterssrv); + if(param->predatfilters) myfree(param->predatfilters); + if(param->datfilterscli) myfree(param->datfilterscli); + if(param->filters){ + if(param->nfilters)while(param->nfilters--){ + if(param->filters[param->nfilters].filter->filter_clear) + (*param->filters[param->nfilters].filter->filter_clear)(param->filters[param->nfilters].data); + } + myfree(param->filters); + } + if(param->connlim) stopconnlims(param); +#endif if(param->srv){ if(param->srv->so.freefunc) param->srv->so.freefunc(param->sostate); pthread_mutex_lock(¶m->srv->counter_mutex);