diff --git a/non-blocking-socket-handling.patch b/non-blocking-socket-handling.patch new file mode 100644 index 0000000..e30acf8 --- /dev/null +++ b/non-blocking-socket-handling.patch @@ -0,0 +1,241 @@ +--- src/client.c 2011-05-02 18:12:53.000000000 +0200 ++++ src/client.c 2011-06-17 15:19:44.000000000 +0200 +@@ -106,10 +106,8 @@ + if(!c->opt->option.retry) + break; + sleep(1); /* FIXME: not a good idea in ucontext threading */ +-#ifndef USE_UCONTEXT + str_stats(); + str_cleanup(); +-#endif + } + } else + run_client(c); +@@ -119,18 +117,17 @@ + #ifdef DEBUG_STACK_SIZE + stack_info(0); /* display computed value */ + #endif ++#ifdef USE_UCONTEXT ++ s_log(LOG_DEBUG, "Context %ld closed", ready_head->id); ++#endif + str_stats(); +-#if defined(USE_WIN32) && !defined(_WIN32_WCE) + str_cleanup(); ++ /* s_log() is not allowed after str_cleanup() */ ++#if defined(USE_WIN32) && !defined(_WIN32_WCE) + _endthread(); + #endif + #ifdef USE_UCONTEXT +- s_log(LOG_DEBUG, "Context %ld closed", ready_head->id); +- /* no str_cleanup() here, as all contexts share the same CPU thread */ + s_poll_wait(NULL, 0, 0); /* wait on poll() */ +- s_log(LOG_ERR, "INTERNAL ERROR: failed to drop context"); +-#else +- str_cleanup(); + #endif + return NULL; + } +@@ -314,9 +320,9 @@ + + while(1) { + #if OPENSSL_VERSION_NUMBER<0x1000002f +- /* this critical section is a crude workaround for CVE-2010-3864 */ +- /* see http://www.securityfocus.com/bid/44884 for details */ +- /* NOTE: this critical section also covers callbacks (e.g. OCSP) */ ++ /* this critical section is a crude workaround for CVE-2010-3864 * ++ * see http://www.securityfocus.com/bid/44884 for details * ++ * NOTE: this critical section also covers callbacks (e.g. OCSP) */ + enter_critical_section(CRIT_SSL); + #endif /* OpenSSL version < 1.0.0b */ + if(c->opt->option.client) +@@ -821,22 +827,26 @@ + type=strchr(line, ':'); + if(!type) { + s_log(LOG_ERR, "Malformed IDENT response"); ++ str_free(line); + longjmp(c->err, 1); + } + *type++='\0'; + system=strchr(type, ':'); + if(!system) { + s_log(LOG_ERR, "Malformed IDENT response"); ++ str_free(line); + longjmp(c->err, 1); + } + *system++='\0'; + if(strcmp(type, " USERID ")) { + s_log(LOG_ERR, "Incorrect INETD response type"); ++ str_free(line); + longjmp(c->err, 1); + } + user=strchr(system, ':'); + if(!user) { + s_log(LOG_ERR, "Malformed IDENT response"); ++ str_free(line); + longjmp(c->err, 1); + } + *user++='\0'; +@@ -846,9 +856,11 @@ + safestring(user); + s_log(LOG_WARNING, "Connection from %s REFUSED by IDENT (user %s)", + c->accepted_address, user); ++ str_free(line); + longjmp(c->err, 1); + } + s_log(LOG_INFO, "IDENT authentication passed"); ++ str_free(line); + } + + #if defined(_WIN32_WCE) || defined(__vms) +@@ -878,8 +890,8 @@ + execname_l=str2tstr(c->opt->execname); + execargs_l=str2tstr(c->opt->execargs); + CreateProcess(execname_l, execargs_l, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); +- free(execname_l); +- free(execargs_l); ++ str_free(execname_l); ++ str_free(execargs_l); + + closesocket(fd[1]); + CloseHandle(pi.hProcess); +@@ -916,6 +928,7 @@ + longjmp(c->err, 1); + case 0: /* child */ + closesocket(fd[0]); ++ set_nonblock(fd[1], 0); /* switch back to blocking mode */ + /* dup2() does not copy FD_CLOEXEC flag */ + dup2(fd[1], 0); + dup2(fd[1], 1); +@@ -969,9 +982,10 @@ + s=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#1"); + if(s<0) + longjmp(c->err, 1); +- fd[1]=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#2"); +- if(fd[1]<0) ++ c->fd=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#2"); ++ if(c->fd<0) + longjmp(c->err, 1); ++ + addrlen=sizeof addr; + memset(&addr, 0, addrlen); + addr.in.sin_family=AF_INET; +@@ -979,22 +993,30 @@ + addr.in.sin_port=htons(0); /* dynamic port allocation */ + if(bind(s, &addr.sa, addrlen)) + log_error(LOG_DEBUG, get_last_socket_error(), "bind#1"); +- if(bind(fd[1], &addr.sa, addrlen)) ++ if(bind(c->fd, &addr.sa, addrlen)) + log_error(LOG_DEBUG, get_last_socket_error(), "bind#2"); ++ + if(listen(s, 1)) { ++ closesocket(s); + sockerror("listen"); + longjmp(c->err, 1); + } + if(getsockname(s, &addr.sa, &addrlen)) { ++ closesocket(s); + sockerror("getsockname"); + longjmp(c->err, 1); + } +- if(connect(fd[1], &addr.sa, addrlen)) { +- sockerror("connect"); ++ if(connect_blocking(c, &addr, addr_len(addr))) { ++ closesocket(s); + longjmp(c->err, 1); + } +- if((fd[0]=s_accept(s, &addr.sa, &addrlen, 1, "accept"))<0) ++ fd[0]=s_accept(s, &addr.sa, &addrlen, 1, "accept"); ++ if(fd[0]<0) { ++ closesocket(s); + longjmp(c->err, 1); ++ } ++ fd[1]=c->fd; ++ c->fd=-1; + closesocket(s); /* don't care about the result */ + #else + if(s_socketpair(AF_UNIX, SOCK_STREAM, 0, fd, 1, "socketpair")) +--- src/stunnel.c 2011/06/18 04:05:08 1.1 ++++ src/stunnel.c 2011/06/18 04:09:42 +@@ -496,11 +496,9 @@ + #endif + + static int setup_fd(int fd, int nonblock, char *msg) { +-#ifdef USE_WIN32 +- unsigned long l; +-#else /* USE_WIN32 */ +- int err, flags; +-#endif /* USE_WIN32 */ ++#ifdef FD_CLOEXEC ++ int err; ++#endif /* FD_CLOEXEC */ + + if(fd<0) { + sockerror(msg); +@@ -512,11 +510,33 @@ + closesocket(fd); + return -1; + } ++ + #ifndef USE_NEW_LINUX_API +-#if defined F_GETFL && defined F_SETFL && defined O_NONBLOCK && !defined __INNOTEK_LIBC__ ++ set_nonblock(fd, nonblock); ++#ifdef FD_CLOEXEC ++ do { ++ err=fcntl(fd, F_SETFD, FD_CLOEXEC); ++ } while(err<0 && get_last_socket_error()==EINTR); ++ if(err<0) ++ sockerror("fcntl SETFD"); /* non-critical */ ++#endif /* FD_CLOEXEC */ ++#endif /* USE_NEW_LINUX_API */ ++ s_log(LOG_DEBUG, "%s: FD=%d allocated (%sblocking mode)", ++ msg, fd, nonblock?"non-":""); ++ return fd; ++} ++ ++void set_nonblock(int fd, unsigned long nonblock) { ++#if defined F_GETFL && defined F_SETFL && defined O_NONBLOCK && !defined __INNOTEK_LIBC__ ++ int err, flags; ++ + do { + flags=fcntl(fd, F_GETFL, 0); + } while(flags<0 && get_last_socket_error()==EINTR); ++ if(flags<0) { ++ sockerror("fcntl GETFL"); /* non-critical */ ++ return; ++ } + if(nonblock) + flags|=O_NONBLOCK; + else +@@ -526,21 +547,10 @@ + } while(err<0 && get_last_socket_error()==EINTR); + if(err<0) + sockerror("fcntl SETFL"); /* non-critical */ +-#ifdef FD_CLOEXEC +- do { +- err=fcntl(fd, F_SETFD, FD_CLOEXEC); +- } while(err<0 && get_last_socket_error()==EINTR); +- if(err<0) +- sockerror("fcntl SETFD"); /* non-critical */ +-#endif /* FD_CLOEXEC */ + #else /* use fcntl() */ +- if(ioctlsocket(fd, FIONBIO, &l)<0) ++ if(ioctlsocket(fd, FIONBIO, &nonblock)<0) + sockerror("ioctlsocket"); /* non-critical */ + #endif /* use fcntl() */ +-#endif /* USE_NEW_LINUX_API */ +- s_log(LOG_DEBUG, "%s: FD=%d allocated (%sblocking mode)", +- msg, fd, nonblock?"non-":""); +- return fd; + } + + /**************************************** log messages to identify build */ +--- src/prototypes.h 2011/06/18 04:05:02 1.1 ++++ src/prototypes.h 2011/06/18 04:06:08 +@@ -256,6 +256,7 @@ + int s_accept(int, struct sockaddr *, socklen_t *, int, char *); + void stunnel_info(int); + void die(int); ++void set_nonblock(int, unsigned long); + + /**************************************** prototypes for log.c */ + diff --git a/stunnel.changes b/stunnel.changes index d8f0ef6..7e3beb2 100644 --- a/stunnel.changes +++ b/stunnel.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Sat Jun 18 03:59:20 UTC 2011 - daniel.rahn@novell.com + +- fix non-blocking socket handling (backport from 4.37) + ------------------------------------------------------------------- Thu Jun 16 11:44:32 UTC 2011 - daniel.rahn@novell.com diff --git a/stunnel.spec b/stunnel.spec index 70fde06..b9dfc19 100644 --- a/stunnel.spec +++ b/stunnel.spec @@ -33,6 +33,7 @@ Source2: stunnel.README Source3: sysconfig.syslog-stunnel Source4: stunnel.rc Patch0: stunnel-listenqueue-option.patch +Patch1: non-blocking-socket-handling.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build %define VENDOR SUSE @@ -50,6 +51,7 @@ without any changes to the program code. %prep %setup -q %patch0 -p0 +%patch1 -p0 %build #autoreconf -fi