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_SIGNAL
|
||||||
CURL_CHECK_FUNC_SIGSETJMP
|
CURL_CHECK_FUNC_SIGSETJMP
|
||||||
CURL_CHECK_FUNC_SOCKET
|
CURL_CHECK_FUNC_SOCKET
|
||||||
|
CURL_CHECK_FUNC_SOCKETPAIR
|
||||||
CURL_CHECK_FUNC_STRCASECMP
|
CURL_CHECK_FUNC_STRCASECMP
|
||||||
CURL_CHECK_FUNC_STRCASESTR
|
CURL_CHECK_FUNC_STRCASESTR
|
||||||
CURL_CHECK_FUNC_STRCMPI
|
CURL_CHECK_FUNC_STRCMPI
|
||||||
|
@ -680,20 +680,20 @@ static void unicodecpy(unsigned char *dest,
|
|||||||
#ifdef USE_NTLM_SSO
|
#ifdef USE_NTLM_SSO
|
||||||
static void sso_ntlm_close(struct connectdata *conn)
|
static void sso_ntlm_close(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
if(conn->fd_helper != -1) {
|
if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
|
||||||
close(conn->fd_helper);
|
sclose(conn->ntlm_auth_hlpr_socket);
|
||||||
conn->fd_helper = -1;
|
conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(conn->pid) {
|
if(conn->ntlm_auth_hlpr_pid) {
|
||||||
int ret, i;
|
int i;
|
||||||
for(i = 0; i < 4; i++) {
|
for(i = 0; i < 4; i++) {
|
||||||
ret = waitpid(conn->pid, NULL, WNOHANG);
|
pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG);
|
||||||
if(ret == conn->pid || errno == ECHILD)
|
if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD)
|
||||||
break;
|
break;
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case 0:
|
case 0:
|
||||||
kill(conn->pid, SIGTERM);
|
kill(conn->ntlm_auth_hlpr_pid, SIGTERM);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* Give the process another moment to shut down cleanly before
|
/* 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);
|
Curl_wait_ms(1);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
kill(conn->pid, SIGKILL);
|
kill(conn->ntlm_auth_hlpr_pid, SIGKILL);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn->pid = 0;
|
conn->ntlm_auth_hlpr_pid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Curl_safefree(conn->challenge_header);
|
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,
|
static CURLcode sso_ntlm_initiate(struct connectdata *conn,
|
||||||
const char *userp)
|
const char *userp)
|
||||||
{
|
{
|
||||||
int sockfds[2];
|
curl_socket_t sockfds[2];
|
||||||
pid_t pid;
|
pid_t child_pid;
|
||||||
const char *username;
|
const char *username;
|
||||||
char *slash, *domain = NULL;
|
char *slash, *domain = NULL;
|
||||||
const char *ntlm_auth = NULL;
|
const char *ntlm_auth = NULL;
|
||||||
@ -728,9 +728,9 @@ static CURLcode sso_ntlm_initiate(struct connectdata *conn,
|
|||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* Return if communication with ntlm_auth already set up */
|
/* 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;
|
return CURLE_OK;
|
||||||
}
|
|
||||||
|
|
||||||
username = userp;
|
username = userp;
|
||||||
slash = strpbrk(username, "\\/");
|
slash = strpbrk(username, "\\/");
|
||||||
@ -768,21 +768,21 @@ static CURLcode sso_ntlm_initiate(struct connectdata *conn,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = fork();
|
child_pid = fork();
|
||||||
if(pid == -1) {
|
if(child_pid == -1) {
|
||||||
error = ERRNO;
|
error = ERRNO;
|
||||||
close(sockfds[0]);
|
sclose(sockfds[0]);
|
||||||
close(sockfds[1]);
|
sclose(sockfds[1]);
|
||||||
failf(conn->data, "Could not fork. errno %d: %s",
|
failf(conn->data, "Could not fork. errno %d: %s",
|
||||||
error, Curl_strerror(conn, error));
|
error, Curl_strerror(conn, error));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if(!pid) {
|
else if(!child_pid) {
|
||||||
/*
|
/*
|
||||||
* child process
|
* child process
|
||||||
*/
|
*/
|
||||||
|
|
||||||
close(sockfds[0]);
|
sclose(sockfds[0]);
|
||||||
|
|
||||||
if(dup2(sockfds[1], STDIN_FILENO) == -1) {
|
if(dup2(sockfds[1], STDIN_FILENO) == -1) {
|
||||||
error = ERRNO;
|
error = ERRNO;
|
||||||
@ -813,14 +813,15 @@ static CURLcode sso_ntlm_initiate(struct connectdata *conn,
|
|||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
error = ERRNO;
|
error = ERRNO;
|
||||||
|
sclose(sockfds[1]);
|
||||||
failf(conn->data, "Could not execl(). errno %d: %s",
|
failf(conn->data, "Could not execl(). errno %d: %s",
|
||||||
error, Curl_strerror(conn, error));
|
error, Curl_strerror(conn, error));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(sockfds[1]);
|
sclose(sockfds[1]);
|
||||||
conn->fd_helper = sockfds[0];
|
conn->ntlm_auth_hlpr_socket = sockfds[0];
|
||||||
conn->pid = pid;
|
conn->ntlm_auth_hlpr_pid = child_pid;
|
||||||
Curl_safefree(domain);
|
Curl_safefree(domain);
|
||||||
Curl_safefree(ntlm_auth_alloc);
|
Curl_safefree(ntlm_auth_alloc);
|
||||||
return CURLE_OK;
|
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);
|
size_t len_in = strlen(input), len_out = sizeof(buf);
|
||||||
|
|
||||||
while(len_in > 0) {
|
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) {
|
if(written == -1) {
|
||||||
/* Interrupted by a signal, retry it */
|
/* Interrupted by a signal, retry it */
|
||||||
if(errno == EINTR)
|
if(errno == EINTR)
|
||||||
@ -853,7 +854,7 @@ static CURLcode sso_ntlm_response(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
/* Read one line */
|
/* Read one line */
|
||||||
while(len_out > 0) {
|
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(size == -1) {
|
||||||
if(errno == EINTR)
|
if(errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@ -946,8 +947,8 @@ CURLcode Curl_output_ntlm_sso(struct connectdata *conn,
|
|||||||
* handling process.
|
* handling process.
|
||||||
*/
|
*/
|
||||||
/* Clean data before using them */
|
/* Clean data before using them */
|
||||||
conn->fd_helper = -1;
|
conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
|
||||||
conn->pid = 0;
|
conn->ntlm_auth_hlpr_pid = 0;
|
||||||
conn->challenge_header = NULL;
|
conn->challenge_header = NULL;
|
||||||
conn->response_header = NULL;
|
conn->response_header = NULL;
|
||||||
/* Create communication with ntlm_auth */
|
/* Create communication with ntlm_auth */
|
||||||
|
@ -285,6 +285,24 @@ curl_socket_t curl_socket(int domain, int type, int protocol,
|
|||||||
return sockfd;
|
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,
|
curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
|
||||||
int line, const char *source)
|
int line, const char *source)
|
||||||
{
|
{
|
||||||
|
@ -65,6 +65,11 @@ CURL_EXTERN int curl_sclose(curl_socket_t sockfd,
|
|||||||
int line , const char *source);
|
int line , const char *source);
|
||||||
CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen,
|
CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen,
|
||||||
int line, const char *source);
|
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 */
|
/* FILE functions */
|
||||||
CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
|
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 */
|
#undef accept /* for those with accept as a macro */
|
||||||
#define accept(sock,addr,len)\
|
#define accept(sock,addr,len)\
|
||||||
curl_accept(sock,addr,len,__LINE__,__FILE__)
|
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
|
#ifdef HAVE_GETADDRINFO
|
||||||
#if defined(getaddrinfo) && defined(__osf__)
|
#if defined(getaddrinfo) && defined(__osf__)
|
||||||
|
@ -908,8 +908,8 @@ struct connectdata {
|
|||||||
#ifdef USE_NTLM_SSO
|
#ifdef USE_NTLM_SSO
|
||||||
/* data used for communication with Samba's winbind daemon helper
|
/* data used for communication with Samba's winbind daemon helper
|
||||||
ntlm_auth */
|
ntlm_auth */
|
||||||
int fd_helper;
|
curl_socket_t ntlm_auth_hlpr_socket;
|
||||||
pid_t pid;
|
pid_t ntlm_auth_hlpr_pid;
|
||||||
char* challenge_header;
|
char* challenge_header;
|
||||||
char* response_header;
|
char* response_header;
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#***************************************************************************
|
#***************************************************************************
|
||||||
|
|
||||||
# File version for 'aclocal' use. Keep it a single number.
|
# File version for 'aclocal' use. Keep it a single number.
|
||||||
# serial 65
|
# serial 66
|
||||||
|
|
||||||
|
|
||||||
dnl CURL_INCLUDES_ARPA_INET
|
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 CURL_CHECK_FUNC_STRCASECMP
|
||||||
dnl -------------------------------------------------
|
dnl -------------------------------------------------
|
||||||
dnl Verify if strcasecmp is available, prototyped, and
|
dnl Verify if strcasecmp is available, prototyped, and
|
||||||
|
@ -236,6 +236,14 @@ while(<FILE>) {
|
|||||||
$getfile{$1}="$source:$linenum";
|
$getfile{$1}="$source:$linenum";
|
||||||
$openfile++;
|
$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*)/) {
|
elsif($function =~ /accept\(\) = (\d*)/) {
|
||||||
$filedes{$1}=1;
|
$filedes{$1}=1;
|
||||||
$getfile{$1}="$source:$linenum";
|
$getfile{$1}="$source:$linenum";
|
||||||
|
Loading…
Reference in New Issue
Block a user