1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

socketpair() usage tracking to allow fd leak detection

This commit is contained in:
Yang Tse 2011-07-29 13:25:52 +02:00
parent 5cdbfa1837
commit bcbac913d6
7 changed files with 156 additions and 30 deletions

View File

@ -2564,6 +2564,7 @@ CURL_CHECK_FUNC_SIGINTERRUPT
CURL_CHECK_FUNC_SIGNAL
CURL_CHECK_FUNC_SIGSETJMP
CURL_CHECK_FUNC_SOCKET
CURL_CHECK_FUNC_SOCKETPAIR
CURL_CHECK_FUNC_STRCASECMP
CURL_CHECK_FUNC_STRCASESTR
CURL_CHECK_FUNC_STRCMPI

View File

@ -680,20 +680,20 @@ static void unicodecpy(unsigned char *dest,
#ifdef USE_NTLM_SSO
static void sso_ntlm_close(struct connectdata *conn)
{
if(conn->fd_helper != -1) {
close(conn->fd_helper);
conn->fd_helper = -1;
if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
sclose(conn->ntlm_auth_hlpr_socket);
conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
}
if(conn->pid) {
int ret, i;
if(conn->ntlm_auth_hlpr_pid) {
int i;
for(i = 0; i < 4; i++) {
ret = waitpid(conn->pid, NULL, WNOHANG);
if(ret == conn->pid || errno == ECHILD)
pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG);
if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD)
break;
switch(i) {
case 0:
kill(conn->pid, SIGTERM);
kill(conn->ntlm_auth_hlpr_pid, SIGTERM);
break;
case 1:
/* Give the process another moment to shut down cleanly before
@ -701,13 +701,13 @@ static void sso_ntlm_close(struct connectdata *conn)
Curl_wait_ms(1);
break;
case 2:
kill(conn->pid, SIGKILL);
kill(conn->ntlm_auth_hlpr_pid, SIGKILL);
break;
case 3:
break;
}
}
conn->pid = 0;
conn->ntlm_auth_hlpr_pid = 0;
}
Curl_safefree(conn->challenge_header);
@ -719,8 +719,8 @@ static void sso_ntlm_close(struct connectdata *conn)
static CURLcode sso_ntlm_initiate(struct connectdata *conn,
const char *userp)
{
int sockfds[2];
pid_t pid;
curl_socket_t sockfds[2];
pid_t child_pid;
const char *username;
char *slash, *domain = NULL;
const char *ntlm_auth = NULL;
@ -728,9 +728,9 @@ static CURLcode sso_ntlm_initiate(struct connectdata *conn,
int error;
/* Return if communication with ntlm_auth already set up */
if(conn->fd_helper != -1 || conn->pid) {
if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
conn->ntlm_auth_hlpr_pid)
return CURLE_OK;
}
username = userp;
slash = strpbrk(username, "\\/");
@ -768,21 +768,21 @@ static CURLcode sso_ntlm_initiate(struct connectdata *conn,
goto done;
}
pid = fork();
if(pid == -1) {
child_pid = fork();
if(child_pid == -1) {
error = ERRNO;
close(sockfds[0]);
close(sockfds[1]);
sclose(sockfds[0]);
sclose(sockfds[1]);
failf(conn->data, "Could not fork. errno %d: %s",
error, Curl_strerror(conn, error));
goto done;
}
else if(!pid) {
else if(!child_pid) {
/*
* child process
*/
close(sockfds[0]);
sclose(sockfds[0]);
if(dup2(sockfds[1], STDIN_FILENO) == -1) {
error = ERRNO;
@ -813,14 +813,15 @@ static CURLcode sso_ntlm_initiate(struct connectdata *conn,
NULL);
error = ERRNO;
sclose(sockfds[1]);
failf(conn->data, "Could not execl(). errno %d: %s",
error, Curl_strerror(conn, error));
exit(1);
}
close(sockfds[1]);
conn->fd_helper = sockfds[0];
conn->pid = pid;
sclose(sockfds[1]);
conn->ntlm_auth_hlpr_socket = sockfds[0];
conn->ntlm_auth_hlpr_pid = child_pid;
Curl_safefree(domain);
Curl_safefree(ntlm_auth_alloc);
return CURLE_OK;
@ -840,7 +841,7 @@ static CURLcode sso_ntlm_response(struct connectdata *conn,
size_t len_in = strlen(input), len_out = sizeof(buf);
while(len_in > 0) {
ssize_t written = write(conn->fd_helper, input, len_in);
ssize_t written = write(conn->ntlm_auth_hlpr_socket, input, len_in);
if(written == -1) {
/* Interrupted by a signal, retry it */
if(errno == EINTR)
@ -853,7 +854,7 @@ static CURLcode sso_ntlm_response(struct connectdata *conn,
}
/* Read one line */
while(len_out > 0) {
size = read(conn->fd_helper, tmpbuf, len_out);
size = read(conn->ntlm_auth_hlpr_socket, tmpbuf, len_out);
if(size == -1) {
if(errno == EINTR)
continue;
@ -946,8 +947,8 @@ CURLcode Curl_output_ntlm_sso(struct connectdata *conn,
* handling process.
*/
/* Clean data before using them */
conn->fd_helper = -1;
conn->pid = 0;
conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
conn->ntlm_auth_hlpr_pid = 0;
conn->challenge_header = NULL;
conn->response_header = NULL;
/* Create communication with ntlm_auth */

View File

@ -285,6 +285,24 @@ curl_socket_t curl_socket(int domain, int type, int protocol,
return sockfd;
}
#ifdef HAVE_SOCKETPAIR
int curl_socketpair(int domain, int type, int protocol,
curl_socket_t socket_vector[2],
int line, const char *source)
{
const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
"FD %s:%d socketpair() = %d %d\n" :
(sizeof(curl_socket_t) == sizeof(long)) ?
"FD %s:%d socketpair() = %ld %ld\n" :
"FD %s:%d socketpair() = %zd %zd\n" ;
int res = socketpair(domain, type, protocol, socket_vector);
if(source && (0 == res))
curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
return res;
}
#endif
curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
int line, const char *source)
{

View File

@ -65,6 +65,11 @@ CURL_EXTERN int curl_sclose(curl_socket_t sockfd,
int line , const char *source);
CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen,
int line, const char *source);
#ifdef HAVE_SOCKETPAIR
CURL_EXTERN int curl_socketpair(int domain, int type, int protocol,
curl_socket_t socket_vector[2],
int line , const char *source);
#endif
/* FILE functions */
CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
@ -90,6 +95,10 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
#undef accept /* for those with accept as a macro */
#define accept(sock,addr,len)\
curl_accept(sock,addr,len,__LINE__,__FILE__)
#ifdef HAVE_SOCKETPAIR
#define socketpair(domain,type,protocol,socket_vector)\
curl_socketpair(domain,type,protocol,socket_vector,__LINE__,__FILE__)
#endif
#ifdef HAVE_GETADDRINFO
#if defined(getaddrinfo) && defined(__osf__)

View File

@ -908,8 +908,8 @@ struct connectdata {
#ifdef USE_NTLM_SSO
/* data used for communication with Samba's winbind daemon helper
ntlm_auth */
int fd_helper;
pid_t pid;
curl_socket_t ntlm_auth_hlpr_socket;
pid_t ntlm_auth_hlpr_pid;
char* challenge_header;
char* response_header;
#endif

View File

@ -21,7 +21,7 @@
#***************************************************************************
# File version for 'aclocal' use. Keep it a single number.
# serial 65
# serial 66
dnl CURL_INCLUDES_ARPA_INET
@ -5624,6 +5624,95 @@ AC_DEFUN([CURL_CHECK_FUNC_SOCKET], [
])
dnl CURL_CHECK_FUNC_SOCKETPAIR
dnl -------------------------------------------------
dnl Verify if socketpair is available, prototyped, and
dnl can be compiled. If all of these are true, and
dnl usage has not been previously disallowed with
dnl shell variable curl_disallow_socketpair, then
dnl HAVE_SOCKETPAIR will be defined.
AC_DEFUN([CURL_CHECK_FUNC_SOCKETPAIR], [
AC_REQUIRE([CURL_INCLUDES_SYS_SOCKET])dnl
AC_REQUIRE([CURL_INCLUDES_SOCKET])dnl
#
tst_links_socketpair="unknown"
tst_proto_socketpair="unknown"
tst_compi_socketpair="unknown"
tst_allow_socketpair="unknown"
#
AC_MSG_CHECKING([if socketpair can be linked])
AC_LINK_IFELSE([
AC_LANG_FUNC_LINK_TRY([socketpair])
],[
AC_MSG_RESULT([yes])
tst_links_socketpair="yes"
],[
AC_MSG_RESULT([no])
tst_links_socketpair="no"
])
#
if test "$tst_links_socketpair" = "yes"; then
AC_MSG_CHECKING([if socketpair is prototyped])
AC_EGREP_CPP([socketpair],[
$curl_includes_sys_socket
$curl_includes_socket
],[
AC_MSG_RESULT([yes])
tst_proto_socketpair="yes"
],[
AC_MSG_RESULT([no])
tst_proto_socketpair="no"
])
fi
#
if test "$tst_proto_socketpair" = "yes"; then
AC_MSG_CHECKING([if socketpair is compilable])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$curl_includes_sys_socket
$curl_includes_socket
]],[[
int sv[2];
if(0 != socketpair(0, 0, 0, sv))
return 1;
]])
],[
AC_MSG_RESULT([yes])
tst_compi_socketpair="yes"
],[
AC_MSG_RESULT([no])
tst_compi_socketpair="no"
])
fi
#
if test "$tst_compi_socketpair" = "yes"; then
AC_MSG_CHECKING([if socketpair usage allowed])
if test "x$curl_disallow_socketpair" != "xyes"; then
AC_MSG_RESULT([yes])
tst_allow_socketpair="yes"
else
AC_MSG_RESULT([no])
tst_allow_socketpair="no"
fi
fi
#
AC_MSG_CHECKING([if socketpair might be used])
if test "$tst_links_socketpair" = "yes" &&
test "$tst_proto_socketpair" = "yes" &&
test "$tst_compi_socketpair" = "yes" &&
test "$tst_allow_socketpair" = "yes"; then
AC_MSG_RESULT([yes])
AC_DEFINE_UNQUOTED(HAVE_SOCKETPAIR, 1,
[Define to 1 if you have the socketpair function.])
ac_cv_func_socketpair="yes"
else
AC_MSG_RESULT([no])
ac_cv_func_socketpair="no"
fi
])
dnl CURL_CHECK_FUNC_STRCASECMP
dnl -------------------------------------------------
dnl Verify if strcasecmp is available, prototyped, and

View File

@ -236,6 +236,14 @@ while(<FILE>) {
$getfile{$1}="$source:$linenum";
$openfile++;
}
elsif($function =~ /socketpair\(\) = (\d*) (\d*)/) {
$filedes{$1}=1;
$getfile{$1}="$source:$linenum";
$openfile++;
$filedes{$2}=1;
$getfile{$2}="$source:$linenum";
$openfile++;
}
elsif($function =~ /accept\(\) = (\d*)/) {
$filedes{$1}=1;
$getfile{$1}="$source:$linenum";