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:
parent
5cdbfa1837
commit
bcbac913d6
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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__)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
Loading…
Reference in New Issue
Block a user