Skip to content

Commit 1d0bc34

Browse files
committed
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
1 parent 0279dda commit 1d0bc34

File tree

1 file changed

+26
-21
lines changed

1 file changed

+26
-21
lines changed

src/core.c

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,10 @@ static int start_chain(int *fd, proxy_data * pd, char *begin_mark) {
462462
error1:
463463
proxychains_write_log(TP " timeout\n");
464464
error:
465-
if(*fd != -1)
465+
if(*fd != -1) {
466466
close(*fd);
467+
*fd = -1;
468+
}
467469
return SOCKET_ERROR;
468470
}
469471

@@ -520,9 +522,9 @@ static unsigned int calc_alive(proxy_data * pd, unsigned int proxy_count) {
520522
}
521523

522524

523-
static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
525+
static int chain_step(int *ns, proxy_data * pfrom, proxy_data * pto) {
524526
int retcode = -1;
525-
char *hostname;
527+
char *hostname, *errmsg = 0;
526528
char hostname_buf[MSG_LEN_MAX];
527529
char ip_buf[INET6_ADDRSTRLEN];
528530
int v6 = pto->ip.is_v6;
@@ -536,31 +538,34 @@ static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
536538
usenumericip:
537539
if(!inet_ntop(v6?AF_INET6:AF_INET,pto->ip.addr.v6,ip_buf,sizeof ip_buf)) {
538540
pto->ps = DOWN_STATE;
539-
proxychains_write_log("<--ip conversion error!\n");
540-
close(ns);
541-
return SOCKET_ERROR;
541+
errmsg = "<--ip conversion error!\n";
542+
retcode = SOCKET_ERROR;
543+
goto err;
542544
}
543545
hostname = ip_buf;
544546
}
545547

546548
proxychains_write_log(TP " %s:%d ", hostname, htons(pto->port));
547-
retcode = tunnel_to(ns, pto->ip, pto->port, pfrom->pt, pfrom->user, pfrom->pass);
549+
retcode = tunnel_to(*ns, pto->ip, pto->port, pfrom->pt, pfrom->user, pfrom->pass);
548550
switch (retcode) {
549551
case SUCCESS:
550552
pto->ps = BUSY_STATE;
551553
break;
552554
case BLOCKED:
553555
pto->ps = BLOCKED_STATE;
554-
proxychains_write_log("<--denied\n");
555-
close(ns);
556-
break;
556+
errmsg = "<--denied\n";
557+
goto err;
557558
case SOCKET_ERROR:
558559
pto->ps = DOWN_STATE;
559-
proxychains_write_log("<--socket error or timeout!\n");
560-
close(ns);
561-
break;
560+
errmsg = "<--socket error or timeout!\n";
561+
goto err;
562562
}
563563
return retcode;
564+
err:
565+
if(errmsg) proxychains_write_log(errmsg);
566+
if(*ns != -1) close(*ns);
567+
*ns = -1;
568+
return retcode;
564569
}
565570

566571
int connect_proxy_chain(int sock, ip_type target_ip,
@@ -596,7 +601,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
596601
p2 = select_proxy(FIFOLY, pd, proxy_count, &offset);
597602
if(!p2)
598603
break;
599-
if(SUCCESS != chain_step(ns, p1, p2)) {
604+
if(SUCCESS != chain_step(&ns, p1, p2)) {
600605
PDEBUG("GOTO AGAIN 1\n");
601606
goto again;
602607
}
@@ -605,7 +610,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
605610
//proxychains_write_log(TP);
606611
p3->ip = target_ip;
607612
p3->port = target_port;
608-
if(SUCCESS != chain_step(ns, p1, p3))
613+
if(SUCCESS != chain_step(&ns, p1, p3))
609614
goto error;
610615
break;
611616

@@ -643,7 +648,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
643648
/* Try from the beginning to where we started */
644649
offset = 0;
645650
continue;
646-
} else if(SUCCESS != chain_step(ns, p1, p2)) {
651+
} else if(SUCCESS != chain_step(&ns, p1, p2)) {
647652
PDEBUG("GOTO AGAIN 1\n");
648653
goto again;
649654
} else
@@ -655,7 +660,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
655660
p3->port = target_port;
656661
proxychains_proxy_offset = offset+1;
657662
PDEBUG("pd_offset = %d, curr_len = %d\n", proxychains_proxy_offset, curr_len);
658-
if(SUCCESS != chain_step(ns, p1, p3))
663+
if(SUCCESS != chain_step(&ns, p1, p3))
659664
goto error;
660665
break;
661666

@@ -673,7 +678,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
673678
while(offset < proxy_count) {
674679
if(!(p2 = select_proxy(FIFOLY, pd, proxy_count, &offset)))
675680
break;
676-
if(SUCCESS != chain_step(ns, p1, p2)) {
681+
if(SUCCESS != chain_step(&ns, p1, p2)) {
677682
PDEBUG("chain_step failed\n");
678683
goto error_strict;
679684
}
@@ -682,7 +687,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
682687
//proxychains_write_log(TP);
683688
p3->ip = target_ip;
684689
p3->port = target_port;
685-
if(SUCCESS != chain_step(ns, p1, p3))
690+
if(SUCCESS != chain_step(&ns, p1, p3))
686691
goto error;
687692
break;
688693

@@ -698,7 +703,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
698703
while(++curr_len < max_chain) {
699704
if(!(p2 = select_proxy(RANDOMLY, pd, proxy_count, &offset)))
700705
goto error_more;
701-
if(SUCCESS != chain_step(ns, p1, p2)) {
706+
if(SUCCESS != chain_step(&ns, p1, p2)) {
702707
PDEBUG("GOTO AGAIN 2\n");
703708
goto again;
704709
}
@@ -707,7 +712,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
707712
//proxychains_write_log(TP);
708713
p3->ip = target_ip;
709714
p3->port = target_port;
710-
if(SUCCESS != chain_step(ns, p1, p3))
715+
if(SUCCESS != chain_step(&ns, p1, p3))
711716
goto error;
712717

713718
}

0 commit comments

Comments
 (0)