aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2014-11-03 18:51:40 -0200
committerAlexandre Oliva <aoliva@redhat.com>2014-11-07 07:18:52 -0200
commit6286965b02069369beeb893833c34f01dc919ffb (patch)
treebf506982de6a7db5f575ed29933b1e0bf7e8b169
parentc83b8a87170cda275a5c591fe2a1d3657d2a6711 (diff)
create all sockets with SOCK_CLOEXEC
-rw-r--r--include/socket-cloexec.h105
-rw-r--r--resolv/res_hconf.c3
-rw-r--r--socket/opensock.c15
-rw-r--r--sunrpc/clnt_tcp.c3
-rw-r--r--sunrpc/clnt_unix.c3
-rw-r--r--sunrpc/pm_getport.c3
-rw-r--r--sunrpc/pmap_rmt.c3
-rw-r--r--sunrpc/rtime.c3
-rw-r--r--sunrpc/svc_tcp.c4
-rw-r--r--sunrpc/svc_udp.c4
-rw-r--r--sunrpc/svc_unix.c3
-rw-r--r--sysdeps/gnu/ifaddrs.c3
-rw-r--r--sysdeps/posix/getaddrinfo.c3
-rw-r--r--sysdeps/unix/sysv/linux/check_native.c4
-rw-r--r--sysdeps/unix/sysv/linux/check_pf.c3
-rw-r--r--sysdeps/unix/sysv/linux/ifaddrs.c3
16 files changed, 144 insertions, 21 deletions
diff --git a/include/socket-cloexec.h b/include/socket-cloexec.h
new file mode 100644
index 0000000000..8ada60497e
--- /dev/null
+++ b/include/socket-cloexec.h
@@ -0,0 +1,105 @@
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SOCKET_CLOEXEC_H
+#define _SOCKET_CLOEXEC_H
+
+#include <stdbool.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+
+/* Like socket, but with SOCK_CLOEXEC set if available. If it's not,
+ try to set the FD_CLOEXEC flag, and if that fails, close the socket
+ and fail unless __tolerant. */
+static inline int
+__socket_cloexec (int __domain, int __type, int __protocol, bool __tolerant)
+{
+ int __ret;
+#ifdef SOCK_CLOEXEC
+# ifdef __ASSUME_SOCK_CLOEXEC
+ int __have_sock_cloexec = 1;
+# endif /* __ASSUME_SOCK_CLOEXEC */
+ if (__have_sock_cloexec >= 0)
+ {
+ __ret = __socket (__domain, __type | SOCK_CLOEXEC, __protocol);
+ if (__have_sock_cloexec == 0)
+ __have_sock_cloexec = (__ret == -1 && errno == EINVAL ? -1 : 1);
+ if (__have_sock_cloexec > 0)
+ return __ret;
+ }
+#endif /* SOCK_CLOEXEC */
+ __ret = __socket (__domain, __type, __protocol);
+
+ if ((__ret >= 0 && __fcntl (__ret, F_SETFD, FD_CLOEXEC) < 0) && !__tolerant)
+ {
+ __close (__ret);
+ __ret = -1;
+ }
+
+ return __ret;
+}
+
+/* Like socket, but with SOCK_CLOEXEC and SOCK_NONBLOCK set if
+ SOCK_CLOEXEC is available. SOCK_NONBLOCK is supported iff
+ SOCK_CLOEXEC is.
+
+ If SOCK_CLOEXEC is not supported, try to set the FD_CLOEXEC flag,
+ and if that fails, close the socket and fail unless __tolerant.
+
+ If SOCK_NONBLOCK is not supported, try to set the O_NONBLOCK flag,
+ and if that fails, close the socket and fail REGARDLESS of
+ __tolerant. */
+static inline int
+__socket_cloexec_nonblock (int __domain, int __type, int __protocol,
+ bool __tolerant)
+{
+ int __ret;
+#ifdef SOCK_NONBLOCK
+# ifdef __ASSUME_SOCK_CLOEXEC
+ int __have_sock_cloexec = 1;
+# endif /* __ASSUME_SOCK_CLOEXEC */
+ if (__have_sock_cloexec >= 0)
+ {
+ __ret = __socket (__domain, __type | SOCK_CLOEXEC | SOCK_NONBLOCK,
+ __protocol);
+ if (__have_sock_cloexec == 0)
+ __have_sock_cloexec = (__ret == -1 && errno == EINVAL ? -1 : 1);
+ if (__have_sock_cloexec > 0)
+ return __ret;
+ }
+#endif /* SOCK_NONBLOCK */
+ __ret = __socket (__domain, __type, __protocol);
+ if (__ret >= 0)
+ {
+ int __fl = __fcntl (__ret, F_GETFL);
+ if (__fl == -1
+ || __fcntl (__ret, F_SETFL, __fl | O_NONBLOCK) < 0
+ || (__fcntl (__ret, F_SETFD, FD_CLOEXEC) < 0 && !__tolerant))
+ {
+ __close (__ret);
+ __ret = -1;
+ }
+ }
+ return __ret;
+}
+
+#pragma poison __socket
+#pragma poison socket
+
+#endif /* _SOCKET_CLOEXEC_H */
diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c
index b4c86227f8..1df336c699 100644
--- a/resolv/res_hconf.c
+++ b/resolv/res_hconf.c
@@ -41,6 +41,7 @@
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
+#include <socket-cloexec.h>
#include <bits/libc-lock.h>
#include "ifreq.h"
#include "res_hconf.h"
@@ -410,7 +411,7 @@ _res_hconf_reorder_addrs (struct hostent *hp)
/* Initialize interface table. */
/* The SIOCGIFNETMASK ioctl will only work on an AF_INET socket. */
- sd = __socket (AF_INET, SOCK_DGRAM, 0);
+ sd = __socket_cloexec (AF_INET, SOCK_DGRAM, 0, true);
if (sd < 0)
return;
diff --git a/socket/opensock.c b/socket/opensock.c
index 8dd89060fa..d23a9624ea 100644
--- a/socket/opensock.c
+++ b/socket/opensock.c
@@ -17,6 +17,7 @@
#include <stdio.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <bits/libc-lock.h>
/* Return a socket of any type. The socket can be used in subsequent
@@ -32,7 +33,7 @@ __opensock (void)
if (sock_af != -1)
{
- fd = __socket (sock_af, SOCK_DGRAM, 0);
+ fd = __socket_cloexec (sock_af, SOCK_DGRAM, 0, true);
if (fd != -1)
return fd;
}
@@ -40,28 +41,28 @@ __opensock (void)
__libc_lock_lock (lock);
if (sock_af != -1)
- fd = __socket (sock_af, SOCK_DGRAM, 0);
+ fd = __socket_cloexec (sock_af, SOCK_DGRAM, 0, true);
if (fd == -1)
{
#ifdef AF_INET
- fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
+ fd = __socket_cloexec (sock_af = AF_INET, SOCK_DGRAM, 0, true);
#endif
#ifdef AF_INET6
if (fd < 0)
- fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
+ fd = __socket_cloexec (sock_af = AF_INET6, SOCK_DGRAM, 0, true);
#endif
#ifdef AF_IPX
if (fd < 0)
- fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0);
+ fd = __socket_cloexec (sock_af = AF_IPX, SOCK_DGRAM, 0, true);
#endif
#ifdef AF_AX25
if (fd < 0)
- fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0);
+ fd = __socket_cloexec (sock_af = AF_AX25, SOCK_DGRAM, 0, true);
#endif
#ifdef AF_APPLETALK
if (fd < 0)
- fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0);
+ fd = __socket_cloexec (sock_af = AF_APPLETALK, SOCK_DGRAM, 0, true);
#endif
}
diff --git a/sunrpc/clnt_tcp.c b/sunrpc/clnt_tcp.c
index f4ba0efe16..2dd07cfa34 100644
--- a/sunrpc/clnt_tcp.c
+++ b/sunrpc/clnt_tcp.c
@@ -52,6 +52,7 @@
#include <rpc/rpc.h>
#include <sys/poll.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <rpc/pmap_clnt.h>
#include <wchar.h>
@@ -146,7 +147,7 @@ clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers,
*/
if (*sockp < 0)
{
- *sockp = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ *sockp = __socket_cloexec (AF_INET, SOCK_STREAM, IPPROTO_TCP, true);
(void) bindresvport (*sockp, (struct sockaddr_in *) 0);
if ((*sockp < 0)
|| (__connect (*sockp, (struct sockaddr *) raddr,
diff --git a/sunrpc/clnt_unix.c b/sunrpc/clnt_unix.c
index aff6fa50df..419a58a76f 100644
--- a/sunrpc/clnt_unix.c
+++ b/sunrpc/clnt_unix.c
@@ -53,6 +53,7 @@
#include <sys/uio.h>
#include <sys/poll.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <rpc/pmap_clnt.h>
#include <wchar.h>
@@ -132,7 +133,7 @@ clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
*/
if (*sockp < 0)
{
- *sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
+ *sockp = __socket_cloexec (AF_UNIX, SOCK_STREAM, 0, true);
len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
if (*sockp < 0
|| __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
diff --git a/sunrpc/pm_getport.c b/sunrpc/pm_getport.c
index d9df0cc35b..31f8dccfff 100644
--- a/sunrpc/pm_getport.c
+++ b/sunrpc/pm_getport.c
@@ -38,6 +38,7 @@
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
/*
* Create a socket that is locally bound to a non-reserve port. For
@@ -48,7 +49,7 @@ int
internal_function
__get_socket (struct sockaddr_in *saddr)
{
- int so = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ int so = __socket_cloexec (AF_INET, SOCK_STREAM, IPPROTO_TCP, true);
if (so < 0)
return -1;
diff --git a/sunrpc/pmap_rmt.c b/sunrpc/pmap_rmt.c
index fd8de85589..389eb9e1be 100644
--- a/sunrpc/pmap_rmt.c
+++ b/sunrpc/pmap_rmt.c
@@ -42,6 +42,7 @@
#include <rpc/pmap_rmt.h>
#include <sys/poll.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <stdio.h>
#include <errno.h>
#undef _POSIX_SOURCE /* Ultrix <sys/param.h> needs --roland@gnu */
@@ -238,7 +239,7 @@ clnt_broadcast (prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
* initialization: create a socket, a broadcast address, and
* preserialize the arguments into a send buffer.
*/
- if ((sock = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ if ((sock = __socket_cloexec (AF_INET, SOCK_DGRAM, IPPROTO_UDP, true)) < 0)
{
perror (_("Cannot create socket for broadcast rpc"));
stat = RPC_CANTSEND;
diff --git a/sunrpc/rtime.c b/sunrpc/rtime.c
index 79d55d1415..48f4681547 100644
--- a/sunrpc/rtime.c
+++ b/sunrpc/rtime.c
@@ -45,6 +45,7 @@
#include <sys/types.h>
#include <sys/poll.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <sys/time.h>
#include <rpc/auth_des.h>
#include <errno.h>
@@ -84,7 +85,7 @@ rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep,
else
type = SOCK_DGRAM;
- s = __socket (AF_INET, type, 0);
+ s = __socket_cloexec (AF_INET, type, 0, true);
if (s < 0)
return (-1);
diff --git a/sunrpc/svc_tcp.c b/sunrpc/svc_tcp.c
index 92886f0869..eaf6297f5a 100644
--- a/sunrpc/svc_tcp.c
+++ b/sunrpc/svc_tcp.c
@@ -58,6 +58,7 @@
#include <libintl.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <sys/poll.h>
#include <errno.h>
#include <stdlib.h>
@@ -159,7 +160,8 @@ svctcp_create (int sock, u_int sendsize, u_int recvsize)
if (sock == RPC_ANYSOCK)
{
- if ((sock = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ if ((sock = __socket_cloexec (AF_INET, SOCK_STREAM, IPPROTO_TCP,
+ true)) < 0)
{
perror (_("svc_tcp.c - tcp socket creation problem"));
return (SVCXPRT *) NULL;
diff --git a/sunrpc/svc_udp.c b/sunrpc/svc_udp.c
index 411234a207..f7a6da1e5d 100644
--- a/sunrpc/svc_udp.c
+++ b/sunrpc/svc_udp.c
@@ -55,6 +55,7 @@
#include <string.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <errno.h>
#include <libintl.h>
@@ -132,7 +133,8 @@ svcudp_bufcreate (sock, sendsz, recvsz)
if (sock == RPC_ANYSOCK)
{
- if ((sock = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ if ((sock = __socket_cloexec (AF_INET, SOCK_DGRAM, IPPROTO_UDP,
+ true)) < 0)
{
perror (_("svcudp_create: socket creation problem"));
return (SVCXPRT *) NULL;
diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c
index 6d93c5f6e5..0d7466d892 100644
--- a/sunrpc/svc_unix.c
+++ b/sunrpc/svc_unix.c
@@ -58,6 +58,7 @@
#include <rpc/rpc.h>
#include <rpc/svc.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <sys/uio.h>
#include <sys/poll.h>
#include <errno.h>
@@ -157,7 +158,7 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
if (sock == RPC_ANYSOCK)
{
- if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ if ((sock = __socket_cloexec (AF_UNIX, SOCK_STREAM, 0, true)) < 0)
{
perror (_("svc_unix.c - AF_UNIX socket creation problem"));
return (SVCXPRT *) NULL;
diff --git a/sysdeps/gnu/ifaddrs.c b/sysdeps/gnu/ifaddrs.c
index 1b8775f013..70db461b04 100644
--- a/sysdeps/gnu/ifaddrs.c
+++ b/sysdeps/gnu/ifaddrs.c
@@ -19,6 +19,7 @@
#include <ifaddrs.h>
#include <net/if.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
@@ -37,7 +38,7 @@ getifaddrs (struct ifaddrs **ifap)
/* This implementation handles only IPv4 interfaces.
The various ioctls below will only work on an AF_INET socket.
Some different mechanism entirely must be used for IPv6. */
- int fd = __socket (AF_INET, SOCK_DGRAM, 0);
+ int fd = __socket_cloexec (AF_INET, SOCK_DGRAM, 0, true);
struct ifreq *ifreqs;
int nifs;
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 8f392b9678..3cbd0334dd 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -52,6 +52,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <net/if.h>
#include <netinet/in.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
@@ -2512,7 +2513,7 @@ getaddrinfo (const char *name, const char *service,
close_retry:
close_not_cancel_no_status (fd);
af = q->ai_family;
- fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
+ fd = __socket_cloexec (af, SOCK_DGRAM, IPPROTO_IP, true);
}
else
{
diff --git a/sysdeps/unix/sysv/linux/check_native.c b/sysdeps/unix/sysv/linux/check_native.c
index 68adeb8771..4a2e143ac5 100644
--- a/sysdeps/unix/sysv/linux/check_native.c
+++ b/sysdeps/unix/sysv/linux/check_native.c
@@ -28,6 +28,8 @@
#include <net/if.h>
#include <net/if_arp.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <asm/types.h>
#include <linux/netlink.h>
@@ -40,7 +42,7 @@ void
__check_native (uint32_t a1_index, int *a1_native,
uint32_t a2_index, int *a2_native)
{
- int fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ int fd = __socket_cloexec (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE, true);
struct sockaddr_nl nladdr;
memset (&nladdr, '\0', sizeof (nladdr));
diff --git a/sysdeps/unix/sysv/linux/check_pf.c b/sysdeps/unix/sysv/linux/check_pf.c
index 976f249e20..a098068a26 100644
--- a/sysdeps/unix/sysv/linux/check_pf.c
+++ b/sysdeps/unix/sysv/linux/check_pf.c
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <stdint.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <asm/types.h>
#include <linux/netlink.h>
@@ -353,7 +354,7 @@ __check_pf (bool *seen_ipv4, bool *seen_ipv6,
}
else
{
- int fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ int fd = __socket_cloexec (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE, true);
if (__glibc_likely (fd >= 0))
{
diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c
index a47b2edcad..aed494ef4e 100644
--- a/sysdeps/unix/sysv/linux/ifaddrs.c
+++ b/sysdeps/unix/sysv/linux/ifaddrs.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <socket-cloexec.h>
#include <sysdep.h>
#include <time.h>
#include <unistd.h>
@@ -251,7 +252,7 @@ __netlink_open (struct netlink_handle *h)
{
struct sockaddr_nl nladdr;
- h->fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ h->fd = __socket_cloexec (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE, true);
if (h->fd < 0)
goto out;