diff options
-rw-r--r-- | include/socket-cloexec.h | 105 | ||||
-rw-r--r-- | resolv/res_hconf.c | 3 | ||||
-rw-r--r-- | socket/opensock.c | 15 | ||||
-rw-r--r-- | sunrpc/clnt_tcp.c | 3 | ||||
-rw-r--r-- | sunrpc/clnt_unix.c | 3 | ||||
-rw-r--r-- | sunrpc/pm_getport.c | 3 | ||||
-rw-r--r-- | sunrpc/pmap_rmt.c | 3 | ||||
-rw-r--r-- | sunrpc/rtime.c | 3 | ||||
-rw-r--r-- | sunrpc/svc_tcp.c | 4 | ||||
-rw-r--r-- | sunrpc/svc_udp.c | 4 | ||||
-rw-r--r-- | sunrpc/svc_unix.c | 3 | ||||
-rw-r--r-- | sysdeps/gnu/ifaddrs.c | 3 | ||||
-rw-r--r-- | sysdeps/posix/getaddrinfo.c | 3 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/check_native.c | 4 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/check_pf.c | 3 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ifaddrs.c | 3 |
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; |