summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbojan <bojan@13f79535-47bb-0310-9956-ffa450edef68>2009-06-12 03:21:22 +0000
committerbojan <bojan@13f79535-47bb-0310-9956-ffa450edef68>2009-06-12 03:21:22 +0000
commitd686d99806301421a734607881afb5fe6584c4d0 (patch)
tree77bb8b73a8798597440f7cb9bfc72c247fa9971f
parent0965fa98405483e5863c2aa6eefb1b1571313700 (diff)
downloadlibapr-d686d99806301421a734607881afb5fe6584c4d0.tar.gz
Backport r747990, r748361, r748371, r748565, r748988, r749810, r783958
from the trunk. Set CLOEXEC flags where appropriate. Either use new O_CLOEXEC flag and associated functions, such as dup3(), accept4(), epoll_create1() etc., or simply set CLOEXEC flag using fcntl(). Patch by Stefan Fritsch <sf sfritsch.de> and Arkadiusz Miskiewicz <arekm pld-linux.org>. PR 46425. fix unused variable warning for builds without HAVE_DUP3 Unroll APR_SET_FD_CLOEXEC macro. * One missing unroll of APR_SET_FD_CLOEXEC. Document CLOEXEC patch. Only set CLOEXEC on dup() if both NOCLEANUP and INHERIT flags are clear. Retain the INHERIT/NOCLEANUP flags of new_file in apr_file_dup2(). Patch by Stefan Fritsch <sf sfritsch.de>. git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/1.4.x@783970 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES5
-rw-r--r--configure.in17
-rw-r--r--file_io/netware/mktemp.c10
-rw-r--r--file_io/unix/filedup.c25
-rw-r--r--file_io/unix/mktemp.c10
-rw-r--r--file_io/unix/open.c29
-rw-r--r--include/arch/unix/apr_arch_inherit.h12
-rw-r--r--network_io/unix/sockets.c46
-rw-r--r--poll/unix/epoll.c35
-rw-r--r--poll/unix/kqueue.c25
-rw-r--r--poll/unix/port.c23
11 files changed, 228 insertions, 9 deletions
diff --git a/CHANGES b/CHANGES
index 9caab6349..2c8e76ae0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
-*- coding: utf-8 -*-
Changes for APR 1.4.0
+ *) Set CLOEXEC flags where appropriate. Either use new O_CLOEXEC flag and
+ associated functions, such as dup3(), accept4(), epoll_create1() etc.,
+ or simply set CLOEXEC flag using fcntl(). PR 46425. [Stefan Fritsch
+ <sf sfritsch.de>, Arkadiusz Miskiewicz <arekm pld-linux.org>]
+
*) Fix compilation error on systems that do not have IPV6.
PR 46601 [Julien Charbon <jch 4js.com>]
diff --git a/configure.in b/configure.in
index e53d9c58d..7e004af21 100644
--- a/configure.in
+++ b/configure.in
@@ -775,6 +775,23 @@ if test "$apr_cv_epoll" = "yes"; then
AC_DEFINE([HAVE_EPOLL], 1, [Define if the epoll interface is supported])
fi
+dnl ----------------------------- Checking for extended file descriptor handling
+AC_CHECK_FUNCS(dup3 accept4 epoll_create1)
+
+AC_CACHE_CHECK([for SOCK_CLOEXEC support], [apr_cv_sock_cloexec],
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int main()
+{
+ return socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0) == -1;
+}], [apr_cv_sock_cloexec=yes], [apr_cv_sock_cloexec=no], [apr_cv_sock_cloexec=no])])
+
+if test "$apr_cv_sock_cloexec" = "yes"; then
+ AC_DEFINE([HAVE_SOCK_CLOEXEC], 1, [Define if the SOCK_CLOEXEC flag is supported])
+fi
+
dnl ----------------------------- Checking for missing POSIX thread functions
AC_CHECK_FUNCS([getpwnam_r getpwuid_r getgrnam_r getgrgid_r])
diff --git a/file_io/netware/mktemp.c b/file_io/netware/mktemp.c
index 2a71af7d6..c86954ff2 100644
--- a/file_io/netware/mktemp.c
+++ b/file_io/netware/mktemp.c
@@ -19,6 +19,7 @@
#include "apr_strings.h" /* prototype of apr_mkstemp() */
#include "apr_arch_file_io.h" /* prototype of apr_mkstemp() */
#include "apr_portable.h" /* for apr_os_file_put() */
+#include "apr_arch_inherit.h"
#include <stdlib.h> /* for mkstemp() - Single Unix */
@@ -43,6 +44,15 @@ APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *template, apr_i
if (!(flags & APR_FILE_NOCLEANUP)) {
+ int flags;
+
+ if ((flags = fcntl((*fp)->filedes, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl((*fp)->filedes, F_SETFD, flags) == -1)
+ return errno;
+
apr_pool_cleanup_register((*fp)->pool, (void *)(*fp),
apr_unix_file_cleanup,
apr_unix_child_file_cleanup);
diff --git a/file_io/unix/filedup.c b/file_io/unix/filedup.c
index adecbb7f0..47ea4f33b 100644
--- a/file_io/unix/filedup.c
+++ b/file_io/unix/filedup.c
@@ -25,13 +25,36 @@ static apr_status_t file_dup(apr_file_t **new_file,
int which_dup)
{
int rv;
-
+#ifdef HAVE_DUP3
+ int flags = 0;
+#endif
+
if (which_dup == 2) {
if ((*new_file) == NULL) {
/* We can't dup2 unless we have a valid new_file */
return APR_EINVAL;
}
+#ifdef HAVE_DUP3
+ if (!((*new_file)->flags & (APR_FILE_NOCLEANUP|APR_INHERIT)))
+ flags |= O_CLOEXEC;
+ rv = dup3(old_file->filedes, (*new_file)->filedes, flags);
+#else
rv = dup2(old_file->filedes, (*new_file)->filedes);
+ if (!((*new_file)->flags & (APR_FILE_NOCLEANUP|APR_INHERIT))) {
+ int flags;
+
+ if (rv == -1)
+ return errno;
+
+ if ((flags = fcntl((*new_file)->filedes, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl((*new_file)->filedes, F_SETFD, flags) == -1)
+ return errno;
+
+ }
+#endif
} else {
rv = dup(old_file->filedes);
}
diff --git a/file_io/unix/mktemp.c b/file_io/unix/mktemp.c
index 22e0bd5d3..a78b73ae9 100644
--- a/file_io/unix/mktemp.c
+++ b/file_io/unix/mktemp.c
@@ -51,6 +51,7 @@
#include "apr_strings.h" /* prototype of apr_mkstemp() */
#include "apr_arch_file_io.h" /* prototype of apr_mkstemp() */
#include "apr_portable.h" /* for apr_os_file_put() */
+#include "apr_arch_inherit.h"
#ifndef HAVE_MKSTEMP
@@ -203,6 +204,15 @@ APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *template, apr_i
(*fp)->fname = apr_pstrdup(p, template);
if (!(flags & APR_FILE_NOCLEANUP)) {
+ int flags;
+
+ if ((flags = fcntl(fd, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl(fd, F_SETFD, flags) == -1)
+ return errno;
+
apr_pool_cleanup_register((*fp)->pool, (void *)(*fp),
apr_unix_file_cleanup,
apr_unix_child_file_cleanup);
diff --git a/file_io/unix/open.c b/file_io/unix/open.c
index a4dce36ae..e10fc3dda 100644
--- a/file_io/unix/open.c
+++ b/file_io/unix/open.c
@@ -127,7 +127,15 @@ APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new,
oflags |= O_BINARY;
}
#endif
-
+
+#ifdef O_CLOEXEC
+ /* Introduced in Linux 2.6.23. Silently ignored on earlier Linux kernels.
+ */
+ if (!(flag & APR_FILE_NOCLEANUP)) {
+ oflags |= O_CLOEXEC;
+}
+#endif
+
#if APR_HAS_LARGE_FILES && defined(_LARGEFILE64_SOURCE)
oflags |= O_LARGEFILE;
#elif defined(O_LARGEFILE)
@@ -155,6 +163,16 @@ APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new,
if (fd < 0) {
return errno;
}
+ if (!(flag & APR_FILE_NOCLEANUP)) {
+ int flags;
+
+ if ((flags = fcntl(fd, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl(fd, F_SETFD, flags) == -1)
+ return errno;
+ }
(*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
(*new)->pool = pool;
@@ -337,6 +355,15 @@ APR_DECLARE(apr_status_t) apr_file_inherit_unset(apr_file_t *thefile)
return APR_EINVAL;
}
if (thefile->flags & APR_INHERIT) {
+ int flags;
+
+ if ((flags = fcntl(thefile->filedes, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl(thefile->filedes, F_SETFD, flags) == -1)
+ return errno;
+
thefile->flags &= ~APR_INHERIT;
apr_pool_child_cleanup_set(thefile->pool,
(void *)thefile,
diff --git a/include/arch/unix/apr_arch_inherit.h b/include/arch/unix/apr_arch_inherit.h
index 9a6bdbca5..6ae2435f0 100644
--- a/include/arch/unix/apr_arch_inherit.h
+++ b/include/arch/unix/apr_arch_inherit.h
@@ -27,6 +27,12 @@ apr_status_t apr_##name##_inherit_set(apr_##name##_t *the##name) \
if (the##name->flag & APR_FILE_NOCLEANUP) \
return APR_EINVAL; \
if (!(the##name->flag & APR_INHERIT)) { \
+ int flags = fcntl(the##name->name##des, F_GETFD); \
+ if (flags == -1) \
+ return errno; \
+ flags &= ~(FD_CLOEXEC); \
+ if (fcntl(the##name->name##des, F_SETFD, flags) == -1) \
+ return errno; \
the##name->flag |= APR_INHERIT; \
apr_pool_child_cleanup_set(the##name->pool, \
(void *)the##name, \
@@ -41,6 +47,12 @@ apr_status_t apr_##name##_inherit_unset(apr_##name##_t *the##name) \
if (the##name->flag & APR_FILE_NOCLEANUP) \
return APR_EINVAL; \
if (the##name->flag & APR_INHERIT) { \
+ int flags; \
+ if ((flags = fcntl(the##name->name##des, F_GETFD)) == -1) \
+ return errno; \
+ flags |= FD_CLOEXEC; \
+ if (fcntl(the##name->name##des, F_SETFD, flags) == -1) \
+ return errno; \
the##name->flag &= ~APR_INHERIT; \
apr_pool_child_cleanup_set(the##name->pool, \
(void *)the##name, \
diff --git a/network_io/unix/sockets.c b/network_io/unix/sockets.c
index 94b26687c..a379b7bdd 100644
--- a/network_io/unix/sockets.c
+++ b/network_io/unix/sockets.c
@@ -83,7 +83,11 @@ apr_status_t apr_socket_protocol_get(apr_socket_t *sock, int *protocol)
apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type,
int protocol, apr_pool_t *cont)
{
- int family = ofamily;
+ int family = ofamily, flags = 0;
+
+#ifdef HAVE_SOCK_CLOEXEC
+ flags |= SOCK_CLOEXEC;
+#endif
if (family == APR_UNSPEC) {
#if APR_HAVE_IPV6
@@ -96,19 +100,19 @@ apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type,
alloc_socket(new, cont);
#ifndef BEOS_R5
- (*new)->socketdes = socket(family, type, protocol);
+ (*new)->socketdes = socket(family, type|flags, protocol);
#else
/* For some reason BeOS R5 has an unconventional protocol numbering,
* so we need to translate here. */
switch (protocol) {
case 0:
- (*new)->socketdes = socket(family, type, 0);
+ (*new)->socketdes = socket(family, type|flags, 0);
break;
case APR_PROTO_TCP:
- (*new)->socketdes = socket(family, type, IPPROTO_TCP);
+ (*new)->socketdes = socket(family, type|flags, IPPROTO_TCP);
break;
case APR_PROTO_UDP:
- (*new)->socketdes = socket(family, type, IPPROTO_UDP);
+ (*new)->socketdes = socket(family, type|flags, IPPROTO_UDP);
break;
case APR_PROTO_SCTP:
default:
@@ -121,7 +125,7 @@ apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type,
#if APR_HAVE_IPV6
if ((*new)->socketdes < 0 && ofamily == APR_UNSPEC) {
family = APR_INET;
- (*new)->socketdes = socket(family, type, protocol);
+ (*new)->socketdes = socket(family, type|flags, protocol);
}
#endif
@@ -130,6 +134,19 @@ apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type,
}
set_socket_vars(*new, family, type, protocol);
+#ifndef HAVE_SOCK_CLOEXEC
+ {
+ int flags;
+
+ if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl((*new)->socketdes, F_SETFD, flags) == -1)
+ return errno;
+ }
+#endif
+
(*new)->timeout = -1;
(*new)->inherit = 0;
apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup,
@@ -181,7 +198,11 @@ apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock,
sa.salen = sizeof(sa.sa);
+#ifdef HAVE_ACCEPT4
+ s = accept4(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen, SOCK_CLOEXEC);
+#else
s = accept(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen);
+#endif
if (s < 0) {
return errno;
@@ -255,6 +276,19 @@ apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock,
(*new)->local_interface_unknown = 1;
}
+#ifndef HAVE_ACCEPT4
+ {
+ int flags;
+
+ if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl((*new)->socketdes, F_SETFD, flags) == -1)
+ return errno;
+ }
+#endif
+
(*new)->inherit = 0;
apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup,
socket_cleanup);
diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c
index c8ab6d63a..0c5fa8f67 100644
--- a/poll/unix/epoll.c
+++ b/poll/unix/epoll.c
@@ -15,6 +15,7 @@
*/
#include "apr_arch_poll_private.h"
+#include "apr_arch_inherit.h"
#ifdef POLLSET_USES_EPOLL
@@ -147,12 +148,29 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
/* Add room for wakeup descriptor */
size++;
}
+#ifdef HAVE_EPOLL_CREATE1
+ fd = epoll_create1(EPOLL_CLOEXEC);
+#else
fd = epoll_create(size);
+#endif
if (fd < 0) {
*pollset = NULL;
return errno;
}
+#ifndef HAVE_EPOLL_CREATE1
+ {
+ int flags;
+
+ if ((flags = fcntl(fd, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl(fd, F_SETFD, flags) == -1)
+ return errno;
+ }
+#endif
+
*pollset = apr_palloc(p, sizeof(**pollset));
#if APR_HAS_THREADS
if ((flags & APR_POLLSET_THREADSAFE) &&
@@ -413,12 +431,29 @@ APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
{
int fd;
+#ifdef HAVE_EPOLL_CREATE1
+ fd = epoll_create1(EPOLL_CLOEXEC);
+#else
fd = epoll_create(size);
+#endif
if (fd < 0) {
*pollcb = NULL;
return apr_get_netos_error();
}
+
+#ifndef HAVE_EPOLL_CREATE1
+ {
+ int flags;
+
+ if ((flags = fcntl(fd, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl(fd, F_SETFD, flags) == -1)
+ return errno;
+ }
+#endif
*pollcb = apr_palloc(p, sizeof(**pollcb));
(*pollcb)->nalloc = size;
diff --git a/poll/unix/kqueue.c b/poll/unix/kqueue.c
index 406eba6e9..34ec1dd42 100644
--- a/poll/unix/kqueue.c
+++ b/poll/unix/kqueue.c
@@ -15,6 +15,7 @@
*/
#include "apr_arch_poll_private.h"
+#include "apr_arch_inherit.h"
#ifdef POLLSET_USES_KQUEUE
@@ -156,6 +157,17 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
return apr_get_netos_error();
}
+ {
+ int flags;
+
+ if ((flags = fcntl((*pollset)->kqueue_fd, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl((*pollset)->kqueue_fd, F_SETFD, flags) == -1)
+ return errno;
+ }
+
(*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
@@ -389,7 +401,18 @@ APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
*pollcb = NULL;
return apr_get_netos_error();
}
-
+
+ {
+ int flags;
+
+ if ((flags = fcntl(fd, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl(fd, F_SETFD, flags) == -1)
+ return errno;
+ }
+
*pollcb = apr_palloc(p, sizeof(**pollcb));
(*pollcb)->nalloc = size;
(*pollcb)->pool = p;
diff --git a/poll/unix/port.c b/poll/unix/port.c
index 73d852511..ab45b9913 100644
--- a/poll/unix/port.c
+++ b/poll/unix/port.c
@@ -16,6 +16,7 @@
#include "apr_arch_poll_private.h"
#include "apr_atomic.h"
+#include "apr_arch_inherit.h"
#ifdef POLLSET_USES_PORT
@@ -181,6 +182,17 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
return APR_ENOMEM;
}
+ {
+ int flags;
+
+ if ((flags = fcntl((*pollset)->port_fd, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl((*pollset)->port_fd, F_SETFD, flags) == -1)
+ return errno;
+ }
+
(*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
@@ -474,6 +486,17 @@ APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
return apr_get_netos_error();
}
+ {
+ int flags;
+
+ if ((flags = fcntl(fd, F_GETFD)) == -1)
+ return errno;
+
+ flags |= FD_CLOEXEC;
+ if (fcntl(fd, F_SETFD, flags) == -1)
+ return errno;
+ }
+
*pollcb = apr_palloc(p, sizeof(**pollcb));
(*pollcb)->nalloc = size;
(*pollcb)->pool = p;