diff options
author | bojan <bojan@13f79535-47bb-0310-9956-ffa450edef68> | 2009-06-12 03:21:22 +0000 |
---|---|---|
committer | bojan <bojan@13f79535-47bb-0310-9956-ffa450edef68> | 2009-06-12 03:21:22 +0000 |
commit | d686d99806301421a734607881afb5fe6584c4d0 (patch) | |
tree | 77bb8b73a8798597440f7cb9bfc72c247fa9971f | |
parent | 0965fa98405483e5863c2aa6eefb1b1571313700 (diff) | |
download | libapr-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-- | CHANGES | 5 | ||||
-rw-r--r-- | configure.in | 17 | ||||
-rw-r--r-- | file_io/netware/mktemp.c | 10 | ||||
-rw-r--r-- | file_io/unix/filedup.c | 25 | ||||
-rw-r--r-- | file_io/unix/mktemp.c | 10 | ||||
-rw-r--r-- | file_io/unix/open.c | 29 | ||||
-rw-r--r-- | include/arch/unix/apr_arch_inherit.h | 12 | ||||
-rw-r--r-- | network_io/unix/sockets.c | 46 | ||||
-rw-r--r-- | poll/unix/epoll.c | 35 | ||||
-rw-r--r-- | poll/unix/kqueue.c | 25 | ||||
-rw-r--r-- | poll/unix/port.c | 23 |
11 files changed, 228 insertions, 9 deletions
@@ -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; |