From 89318bbeb4076d8d9de9831d69621fc1411760d3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 May 2009 03:41:50 +0200 Subject: cloexec: set all sockets that are created with SOCK_CLOEXEC Since all socket users enable FD_CLOEXEC anyway we can just do that in _dbus_open_socket() and be done with it for all cases. By side effect this allows us to use SOCK_CLOEXEC and hence close the CLOEXEC race. --- dbus/dbus-server-socket.c | 5 ---- dbus/dbus-server-unix.c | 3 +-- dbus/dbus-sysdeps-unix.c | 62 ++++++++++++++++++++++++++++++++++++++++---- dbus/dbus-transport-socket.c | 2 -- dbus/dbus-transport-unix.c | 2 -- 5 files changed, 58 insertions(+), 16 deletions(-) (limited to 'dbus') diff --git a/dbus/dbus-server-socket.c b/dbus/dbus-server-socket.c index 0cd2bb6c..b663e49d 100644 --- a/dbus/dbus-server-socket.c +++ b/dbus/dbus-server-socket.c @@ -195,8 +195,6 @@ socket_handle_watch (DBusWatch *watch, } else { - _dbus_fd_set_close_on_exec (client_fd); - if (!handle_new_client_fd_and_unlock (server, client_fd)) _dbus_verbose ("Rejected client connection due to lack of memory\n"); } @@ -413,9 +411,6 @@ _dbus_server_new_for_tcp_socket (const char *host, goto failed_1; } - for (i = 0 ; i < nlisten_fds ; i++) - _dbus_fd_set_close_on_exec (listen_fds[i]); - _dbus_string_init_const (&host_str, host); if (!_dbus_string_append (&address, "tcp:host=") || !_dbus_address_append_escaped (&address, &host_str) || diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index 1dda5d19..86a64c86 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -201,8 +201,7 @@ _dbus_server_new_for_domain_socket (const char *path, } listen_fd = _dbus_listen_unix_socket (path, abstract, error); - _dbus_fd_set_close_on_exec (listen_fd); - + if (listen_fd < 0) { _DBUS_ASSERT_ERROR_IS_SET (error); diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 9631be18..3312bd17 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -94,9 +94,28 @@ _dbus_open_socket (int *fd_p, int protocol, DBusError *error) { - *fd_p = socket (domain, type, protocol); +#ifdef SOCK_CLOEXEC + dbus_bool_t cloexec_done; + + *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol); + cloexec_done = *fd_p >= 0; + + /* Check if kernel seems to be too old to know SOCK_CLOEXEC */ + if (*fd_p < 0 && errno == EINVAL) +#endif + { + *fd_p = socket (domain, type, protocol); + } + if (*fd_p >= 0) { +#ifdef SOCK_CLOEXEC + if (!cloexec_done) +#endif + { + _dbus_fd_set_close_on_exec(*fd_p); + } + _dbus_verbose ("socket fd %d opened\n", *fd_p); return TRUE; } @@ -120,6 +139,9 @@ _dbus_open_tcp_socket (int *fd, /** * Opens a UNIX domain socket (as in the socket() call). * Does not bind the socket. + * + * This will set FD_CLOEXEC for the socket returned + * * @param fd return location for socket descriptor * @param error return location for an error * @returns #FALSE if error is set @@ -770,6 +792,8 @@ _dbus_write_two (int fd, * requested (it's possible only on Linux; see "man 7 unix" on Linux). * On non-Linux abstract socket usage always fails. * + * This will set FD_CLOEXEC for the socket returned. + * * @param path the path to UNIX domain socket * @param abstract #TRUE to use abstract namespace * @param error return location for error code @@ -906,6 +930,8 @@ _dbus_set_local_creds (int fd, dbus_bool_t on) * see "man 7 unix" on Linux). * On non-Linux abstract socket usage always fails. * + * This will set FD_CLOEXEC for the socket returned + * * @param path the socket name * @param abstract #TRUE to use abstract namespace * @param error return location for errors @@ -1042,6 +1068,8 @@ _dbus_listen_unix_socket (const char *path, * and port. The connection fd is returned, and is set up as * nonblocking. * + * This will set FD_CLOEXEC for the socket returned + * * @param host the host name to connect to * @param port the port to connect to * @param family the address family to listen on, NULL for all @@ -1149,6 +1177,8 @@ _dbus_connect_tcp_socket (const char *host, * a random free port is used and returned in the port parameter. * If inaddr_any is specified, the hostname is ignored. * + * This will set FD_CLOEXEC for the socket returned + * * @param host the host name to listen on * @param port the port to listen on, if zero a free port will be used * @param family the address family to listen on, NULL for all @@ -1669,6 +1699,8 @@ _dbus_send_credentials_socket (int server_fd, * Accepts a connection on a listening socket. * Handles EINTR for you. * + * This will enable FD_CLOEXEC for the returned socket. + * * @param listen_fd the listen file descriptor * @returns the connection fd of the client, or -1 on error */ @@ -1678,12 +1710,25 @@ _dbus_accept (int listen_fd) int client_fd; struct sockaddr addr; socklen_t addrlen; +#ifdef HAVE_ACCEPT4 + dbus_bool_t cloexec_done; +#endif addrlen = sizeof (addr); - + retry: - client_fd = accept (listen_fd, &addr, &addrlen); - + +#ifdef HAVE_ACCEPT4 + /* We assume that if accept4 is available SOCK_CLOEXEC is too */ + client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC); + cloexec_done = client_fd >= 0; + + if (client_fd < 0 && errno == ENOSYS) +#endif + { + client_fd = accept (listen_fd, &addr, &addrlen); + } + if (client_fd < 0) { if (errno == EINTR) @@ -1691,7 +1736,14 @@ _dbus_accept (int listen_fd) } _dbus_verbose ("client fd %d accepted\n", client_fd); - + +#ifdef HAVE_ACCEPT4 + if (!cloexec_done) +#endif + { + _dbus_fd_set_close_on_exec(client_fd); + } + return client_fd; } diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index c9d4d93c..cc49c851 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -1324,8 +1324,6 @@ _dbus_transport_new_for_tcp_socket (const char *host, return NULL; } - _dbus_fd_set_close_on_exec (fd); - _dbus_verbose ("Successfully connected to tcp socket %s:%s\n", host, port); diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index a13fde17..777c9411 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -85,8 +85,6 @@ _dbus_transport_new_for_domain_socket (const char *path, goto failed_0; } - _dbus_fd_set_close_on_exec (fd); - _dbus_verbose ("Successfully connected to unix socket %s\n", path); -- cgit