fix potential double-close of file descriptors

in case of an error condition, both start_chain() and chain_step()
were closing the fd to be acted upon, without setting it to -1,
and the function calling them would close them again.

this could affect multi-threaded applications that opened new fds
between the first and the second close, invalidating those fds
in the targeted app.

patch loosely based on report and PR by @jhfrontz.

closes #542
This commit is contained in:
rofl0r 2024-01-02 14:45:25 +00:00
parent 0279dda939
commit 1d0bc349eb

View File

@ -462,8 +462,10 @@ static int start_chain(int *fd, proxy_data * pd, char *begin_mark) {
error1: error1:
proxychains_write_log(TP " timeout\n"); proxychains_write_log(TP " timeout\n");
error: error:
if(*fd != -1) if(*fd != -1) {
close(*fd); close(*fd);
*fd = -1;
}
return SOCKET_ERROR; return SOCKET_ERROR;
} }
@ -520,9 +522,9 @@ static unsigned int calc_alive(proxy_data * pd, unsigned int proxy_count) {
} }
static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) { static int chain_step(int *ns, proxy_data * pfrom, proxy_data * pto) {
int retcode = -1; int retcode = -1;
char *hostname; char *hostname, *errmsg = 0;
char hostname_buf[MSG_LEN_MAX]; char hostname_buf[MSG_LEN_MAX];
char ip_buf[INET6_ADDRSTRLEN]; char ip_buf[INET6_ADDRSTRLEN];
int v6 = pto->ip.is_v6; int v6 = pto->ip.is_v6;
@ -536,31 +538,34 @@ static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
usenumericip: usenumericip:
if(!inet_ntop(v6?AF_INET6:AF_INET,pto->ip.addr.v6,ip_buf,sizeof ip_buf)) { if(!inet_ntop(v6?AF_INET6:AF_INET,pto->ip.addr.v6,ip_buf,sizeof ip_buf)) {
pto->ps = DOWN_STATE; pto->ps = DOWN_STATE;
proxychains_write_log("<--ip conversion error!\n"); errmsg = "<--ip conversion error!\n";
close(ns); retcode = SOCKET_ERROR;
return SOCKET_ERROR; goto err;
} }
hostname = ip_buf; hostname = ip_buf;
} }
proxychains_write_log(TP " %s:%d ", hostname, htons(pto->port)); proxychains_write_log(TP " %s:%d ", hostname, htons(pto->port));
retcode = tunnel_to(ns, pto->ip, pto->port, pfrom->pt, pfrom->user, pfrom->pass); retcode = tunnel_to(*ns, pto->ip, pto->port, pfrom->pt, pfrom->user, pfrom->pass);
switch (retcode) { switch (retcode) {
case SUCCESS: case SUCCESS:
pto->ps = BUSY_STATE; pto->ps = BUSY_STATE;
break; break;
case BLOCKED: case BLOCKED:
pto->ps = BLOCKED_STATE; pto->ps = BLOCKED_STATE;
proxychains_write_log("<--denied\n"); errmsg = "<--denied\n";
close(ns); goto err;
break;
case SOCKET_ERROR: case SOCKET_ERROR:
pto->ps = DOWN_STATE; pto->ps = DOWN_STATE;
proxychains_write_log("<--socket error or timeout!\n"); errmsg = "<--socket error or timeout!\n";
close(ns); goto err;
break;
} }
return retcode; return retcode;
err:
if(errmsg) proxychains_write_log(errmsg);
if(*ns != -1) close(*ns);
*ns = -1;
return retcode;
} }
int connect_proxy_chain(int sock, ip_type target_ip, int connect_proxy_chain(int sock, ip_type target_ip,
@ -596,7 +601,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
p2 = select_proxy(FIFOLY, pd, proxy_count, &offset); p2 = select_proxy(FIFOLY, pd, proxy_count, &offset);
if(!p2) if(!p2)
break; break;
if(SUCCESS != chain_step(ns, p1, p2)) { if(SUCCESS != chain_step(&ns, p1, p2)) {
PDEBUG("GOTO AGAIN 1\n"); PDEBUG("GOTO AGAIN 1\n");
goto again; goto again;
} }
@ -605,7 +610,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
//proxychains_write_log(TP); //proxychains_write_log(TP);
p3->ip = target_ip; p3->ip = target_ip;
p3->port = target_port; p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3)) if(SUCCESS != chain_step(&ns, p1, p3))
goto error; goto error;
break; break;
@ -643,7 +648,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
/* Try from the beginning to where we started */ /* Try from the beginning to where we started */
offset = 0; offset = 0;
continue; continue;
} else if(SUCCESS != chain_step(ns, p1, p2)) { } else if(SUCCESS != chain_step(&ns, p1, p2)) {
PDEBUG("GOTO AGAIN 1\n"); PDEBUG("GOTO AGAIN 1\n");
goto again; goto again;
} else } else
@ -655,7 +660,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
p3->port = target_port; p3->port = target_port;
proxychains_proxy_offset = offset+1; proxychains_proxy_offset = offset+1;
PDEBUG("pd_offset = %d, curr_len = %d\n", proxychains_proxy_offset, curr_len); PDEBUG("pd_offset = %d, curr_len = %d\n", proxychains_proxy_offset, curr_len);
if(SUCCESS != chain_step(ns, p1, p3)) if(SUCCESS != chain_step(&ns, p1, p3))
goto error; goto error;
break; break;
@ -673,7 +678,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
while(offset < proxy_count) { while(offset < proxy_count) {
if(!(p2 = select_proxy(FIFOLY, pd, proxy_count, &offset))) if(!(p2 = select_proxy(FIFOLY, pd, proxy_count, &offset)))
break; break;
if(SUCCESS != chain_step(ns, p1, p2)) { if(SUCCESS != chain_step(&ns, p1, p2)) {
PDEBUG("chain_step failed\n"); PDEBUG("chain_step failed\n");
goto error_strict; goto error_strict;
} }
@ -682,7 +687,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
//proxychains_write_log(TP); //proxychains_write_log(TP);
p3->ip = target_ip; p3->ip = target_ip;
p3->port = target_port; p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3)) if(SUCCESS != chain_step(&ns, p1, p3))
goto error; goto error;
break; break;
@ -698,7 +703,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
while(++curr_len < max_chain) { while(++curr_len < max_chain) {
if(!(p2 = select_proxy(RANDOMLY, pd, proxy_count, &offset))) if(!(p2 = select_proxy(RANDOMLY, pd, proxy_count, &offset)))
goto error_more; goto error_more;
if(SUCCESS != chain_step(ns, p1, p2)) { if(SUCCESS != chain_step(&ns, p1, p2)) {
PDEBUG("GOTO AGAIN 2\n"); PDEBUG("GOTO AGAIN 2\n");
goto again; goto again;
} }
@ -707,7 +712,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
//proxychains_write_log(TP); //proxychains_write_log(TP);
p3->ip = target_ip; p3->ip = target_ip;
p3->port = target_port; p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3)) if(SUCCESS != chain_step(&ns, p1, p3))
goto error; goto error;
} }