BZ#15722: create all sockets with SOCK_CLOEXEC

Message ID orzjbuy121.fsf@free.home
State Dropped
Headers

Commit Message

Alexandre Oliva Nov. 14, 2014, 2:21 a.m. UTC
  Here's a revised patch that moves __sock_cloexec to its own header,
dropping the __need* ugliness that had been introduced to fix the mutual
inclusion of headers.  How's this?


for ChangeLog

	[BZ #15722]
	* NEWS: Updated.
	* resolv/res_hconf.c (_res_hconf_reorder_addrs): Call
	__socket_cloexec.
	* socket/opensock.c: Likewise.
	* sunrpc/clnt_tcp.c (clnttcp_create): Likewise.
	* sunrpc/clnt_unix.c (clntunix_create): Likewise.
	* sunrpc/pm_getport.c (__get_socket): Likewise.
	* sunrpc/pmap_rmt.c (clnt_broadcast): Likewise.
	* sunrpc/rtime.c (rtime): Likewise.
	* sunrpc/svc_tcp.c (svctcp_create): Likewise.
	* sunrpc/svc_udp.c (svcudp_bufcreate): Likewise.
	* sunrpc/svc_unix.c (svcunix_create): Likewise.
	* sysdeps/gnu/ifaddrs.c (getifaddrs): Likewise.
	* sysdeps/posix/getaddrinfo.c (getaddrinfo): Likewise.
	* sysdeps/unix/sysv/linux/check_native.c (__check_native):
	Likewise.
	* sysdeps/unix/sysv/linux/check_pf.c (__check_pf): Likewise.
	* sysdeps/unix/sysv/linux/ifaddrs.c (__netlink_open):
	Likewise.
	* include/socket-cloexec.h: New header, included instead of
	sys/socket.h in all of the above.
	* nscd/gai.c: Include socket/have_sock_cloexec.c.
	* posix/tst-rfc3484.c, posix/tst-rfc3484-2.c,
	posix/tst-rfc3484-3.c: Factor out common getaddrinfo testing
	infrastructure into...
	* posix/tst-rfc3484.h: ... this new header.  Include
	socket/have_sock_cloexec.c.  Define __f into f before
	including headers.
---
 include/socket-cloexec.h               |   69 ++++++++++++++++++++++++++++
 nscd/gai.c                             |    1 
 posix/tst-rfc3484-2.c                  |   80 --------------------------------
 posix/tst-rfc3484-3.c                  |   80 --------------------------------
 posix/tst-rfc3484.c                    |   80 --------------------------------
 posix/tst-rfc3484.h                    |   77 +++++++++++++++++++++++++++++++
 resolv/res_hconf.c                     |    3 +
 socket/opensock.c                      |   16 +++---
 sunrpc/clnt_tcp.c                      |    4 +-
 sunrpc/clnt_unix.c                     |    4 +-
 sunrpc/pm_getport.c                    |    4 +-
 sunrpc/pmap_rmt.c                      |    4 +-
 sunrpc/rtime.c                         |    4 +-
 sunrpc/svc_tcp.c                       |    4 +-
 sunrpc/svc_udp.c                       |    4 +-
 sunrpc/svc_unix.c                      |    4 +-
 sysdeps/gnu/ifaddrs.c                  |    4 +-
 sysdeps/posix/getaddrinfo.c            |    4 +-
 sysdeps/unix/sysv/linux/check_native.c |    3 +
 sysdeps/unix/sysv/linux/check_pf.c     |    4 +-
 sysdeps/unix/sysv/linux/ifaddrs.c      |    4 +-
 21 files changed, 186 insertions(+), 271 deletions(-)
 create mode 100644 include/socket-cloexec.h
 create mode 100644 posix/tst-rfc3484.h
  

Comments

Alexandre Oliva Dec. 9, 2014, 5:53 p.m. UTC | #1
On Nov 14, 2014, Alexandre Oliva <aoliva@redhat.com> wrote:

> Here's a revised patch that moves __sock_cloexec to its own header,
> dropping the __need* ugliness that had been introduced to fix the mutual
> inclusion of headers.  How's this?

Ping?
https://sourceware.org/ml/libc-alpha/2014-11/msg00335.html

> for ChangeLog

> 	[BZ #15722]
> 	* NEWS: Updated.
> 	* resolv/res_hconf.c (_res_hconf_reorder_addrs): Call
> 	__socket_cloexec.
> 	* socket/opensock.c: Likewise.
> 	* sunrpc/clnt_tcp.c (clnttcp_create): Likewise.
> 	* sunrpc/clnt_unix.c (clntunix_create): Likewise.
> 	* sunrpc/pm_getport.c (__get_socket): Likewise.
> 	* sunrpc/pmap_rmt.c (clnt_broadcast): Likewise.
> 	* sunrpc/rtime.c (rtime): Likewise.
> 	* sunrpc/svc_tcp.c (svctcp_create): Likewise.
> 	* sunrpc/svc_udp.c (svcudp_bufcreate): Likewise.
> 	* sunrpc/svc_unix.c (svcunix_create): Likewise.
> 	* sysdeps/gnu/ifaddrs.c (getifaddrs): Likewise.
> 	* sysdeps/posix/getaddrinfo.c (getaddrinfo): Likewise.
> 	* sysdeps/unix/sysv/linux/check_native.c (__check_native):
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/check_pf.c (__check_pf): Likewise.
> 	* sysdeps/unix/sysv/linux/ifaddrs.c (__netlink_open):
> 	Likewise.
> 	* include/socket-cloexec.h: New header, included instead of
> 	sys/socket.h in all of the above.
> 	* nscd/gai.c: Include socket/have_sock_cloexec.c.
> 	* posix/tst-rfc3484.c, posix/tst-rfc3484-2.c,
> 	posix/tst-rfc3484-3.c: Factor out common getaddrinfo testing
> 	infrastructure into...
> 	* posix/tst-rfc3484.h: ... this new header.  Include
> 	socket/have_sock_cloexec.c.  Define __f into f before
> 	including headers.
  
Ondrej Bilka Dec. 11, 2014, 1:17 p.m. UTC | #2
On Tue, Dec 09, 2014 at 03:53:46PM -0200, Alexandre Oliva wrote:
> On Nov 14, 2014, Alexandre Oliva <aoliva@redhat.com> wrote:
> 
> > Here's a revised patch that moves __sock_cloexec to its own header,
> > dropping the __need* ugliness that had been introduced to fix the mutual
> > inclusion of headers.  How's this?
> 
> Ping?
> https://sourceware.org/ml/libc-alpha/2014-11/msg00335.html
> 
Its ok from code perspective, but only internal sockets could use
CLOEXEC. Could you clarify why for sunrpc user cannot do trick of saving
sockets in file, then restarting with exec and reading file to keep
socket alive?
  
Roland McGrath Dec. 11, 2014, 7:29 p.m. UTC | #3
> 	* NEWS: Updated.

There is no NEWS change in your patch.  If the only change was adding to
the list of fixed BZ#s, that does not get mentioned in ChangeLog.

> --- /dev/null
> +++ b/include/socket-cloexec.h
> @@ -0,0 +1,69 @@
> +/* Copyright (C) 2014 Free Software Foundation, Inc.

Top line of every new file must be a descriptive comment.

> +/* 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.  */

What is __tolerant?

> +#ifdef FD_CLOEXEC
> +  if (ret != -1)
> +    {
> +      int flags = __fcntl (ret, F_GETFD, 0);
> +      if (flags == -1
> +	  || __fcntl (ret, F_SETFD, flags | FD_CLOEXEC) == -1)
> +	{
> +	  __close (ret);
> +	  ret = -1;
> +	  errno = EINVAL;

How did you decide on EINVAL for this case?
It needs a comment.

> +#pragma poison __socket
> +#pragma poison socket

cf. a previous review about introducing '#pragma poison'.

> --- 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);
>        if (sd < 0)
>  	return;

This is a temporary fd used only within this function, never left open.
If there is no underlying SOCK_CLOEXEC support, then calling fcntl after
the fact is no more guarantee of anything than calling close in this
function (and adds some overhead).  My inclination is not to pretend to
offer any race-free leaklessness if we cannot in fact offer it across
the board.

Sure, it's nice to be leakless when it's cheap and race-free to be so.
But it's not part of the API that you can rely on this, and cannot be
unless we require underlying SOCK_CLOEXEC support for every
implementation of the GNU C API.  That would say that for these
ephemeral uses, we use SOCK_CLOEXEC if it's available but do not bother
with the fcntl call if it's not.

Perhaps we actually can require SOCK_CLOEXEC support nowadays, but we
haven't ever explicitly said so before.  (For Linux configurations,
__ASSUME_SOCK_CLOEXEC is always set since we now support only kernels
new enough.  For the Hurd, *_CLOEXEC are actually implemented entirely
in libc, though SOCK_CLOEXEC is not actually implemented yet.  The other
OS port forthcoming is NaCl, which does not have exec at all yet.)

> @@ -146,7 +146,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);
>        (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
>        if ((*sockp < 0)
>  	  || (__connect (*sockp, (struct sockaddr *) raddr,

This is a change in user semantics.  It definitely doesn't belong in the
same change with the ephemeral cases, and probably it's an unacceptable
API change.  For this completely deprecated API, it's not worth making
any changes.

> @@ -132,7 +132,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);
>        len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
>        if (*sockp < 0
>  	  || __connect (*sockp, (struct sockaddr *) raddr, len) < 0)

Same here.

> @@ -48,7 +48,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);
>    if (so < 0)
>      return -1;

This one is OK as far as being a proper ephemeral case, but I'd still be
inclined just not to touch any sunrpc/ code at all.


Thanks,
Roland
  
Ondrej Bilka Dec. 11, 2014, 8:39 p.m. UTC | #4
On Thu, Dec 11, 2014 at 11:29:34AM -0800, Roland McGrath wrote:
> 
> This is a temporary fd used only within this function, never left open.
> If there is no underlying SOCK_CLOEXEC support, then calling fcntl after
> the fact is no more guarantee of anything than calling close in this
> function (and adds some overhead).  My inclination is not to pretend to
> offer any race-free leaklessness if we cannot in fact offer it across
> the board.
>
and
 
> Perhaps we actually can require SOCK_CLOEXEC support nowadays, but we
> haven't ever explicitly said so before.  (For Linux configurations,
> __ASSUME_SOCK_CLOEXEC is always set since we now support only kernels
> new enough.  For the Hurd, *_CLOEXEC are actually implemented entirely
> in libc, though SOCK_CLOEXEC is not actually implemented yet.  The other
> OS port forthcoming is NaCl, which does not have exec at all yet.)
>
At least it allows skip fcntl part entirely, linux is not problem and
for other systems should add both at same time, or we could handle
SOCK_CLOEXEC in wrapper by fcntl.
  
Thomas Schwinge Dec. 12, 2014, 6:20 a.m. UTC | #5
Hi!

On Thu, 11 Dec 2014 11:29:34 -0800 (PST), Roland McGrath <roland@hack.frob.com> wrote:
> Perhaps we actually can require SOCK_CLOEXEC support nowadays, but we
> haven't ever explicitly said so before.  (For Linux configurations,
> __ASSUME_SOCK_CLOEXEC is always set since we now support only kernels
> new enough.  For the Hurd, *_CLOEXEC are actually implemented entirely
> in libc, though SOCK_CLOEXEC is not actually implemented yet.

I have pending patches for the latter -- from 2008 ;-) -- which just need
some cleanup before integration, but which we've been using ever since in
our internal glibc maintenance branch, so don't let that be a hindrance.


Grüße,
 Thomas
  
Alexandre Oliva Dec. 16, 2014, 6:15 p.m. UTC | #6
On Dec 11, 2014, Roland McGrath <roland@hack.frob.com> wrote:

>> * NEWS: Updated.
> There is no NEWS change in your patch.  If the only change was adding to
> the list of fixed BZ#s, that does not get mentioned in ChangeLog.

Ack, thanks.

>> --- /dev/null
>> +++ b/include/socket-cloexec.h
>> @@ -0,0 +1,69 @@
>> +/* Copyright (C) 2014 Free Software Foundation, Inc.

> Top line of every new file must be a descriptive comment.

Thanks, fixed.

>> +/* 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.  */

> What is __tolerant?

Left-over from an earlier version of the patch.  Thanks, fixed.

>> +#ifdef FD_CLOEXEC
>> +  if (ret != -1)
>> +    {
>> +      int flags = __fcntl (ret, F_GETFD, 0);
>> +      if (flags == -1
>> +	  || __fcntl (ret, F_SETFD, flags | FD_CLOEXEC) == -1)
>> +	{
>> +	  __close (ret);
>> +	  ret = -1;
>> +	  errno = EINVAL;

> How did you decide on EINVAL for this case?
> It needs a comment.

	  /* EINVAL is what __socket returns if it does not support
	     SOCK_CLOEXEC.  */

>> +#pragma poison __socket
>> +#pragma poison socket

> cf. a previous review about introducing '#pragma poison'.

*nod*

I see now that this is wrong in this case.  See below.

> This is a temporary fd used only within this function, never left open.
> If there is no underlying SOCK_CLOEXEC support, then calling fcntl after
> the fact is no more guarantee of anything than calling close in this
> function (and adds some overhead).  My inclination is not to pretend to
> offer any race-free leaklessness if we cannot in fact offer it across
> the board.

The goal was never to offer a race-free SOCK_CLOEXEC-equivalent.  As far
as I was concerned, initially it was just to attempt to reduce the
internal fd count left over after exec.

Adding the FD_CLOEXEC fallback was just an idea I got from one of the
rpc sources that used it.  Maybe we don't want to do that there either?

Anyway, since it was meant to be best-effort (we can't assume
SOCK_CLOEXEC or even FD_CLOEXEC are supported), it wouldn't make much
sense to require it to be atomic either.  And given that it was
best-effort, under the reasoning that we'd better get a socket without
cloexec than not get one at all, I dropped __tolerant, which was meant
to choose between failing altogether or accepting getting a socket
without cloexec.  The latest patch still had some intolerant code, that
closed the socket if FD_CLOEXEC didn't work, though; I guess that's a
symptom of the patch not having a well-defined goal, shifting about as
suggestions and requests come about ;-)

>> @@ -146,7 +146,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);
>> (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
>> if ((*sockp < 0)
>> || (__connect (*sockp, (struct sockaddr *) raddr,

> This is a change in user semantics.  It definitely doesn't belong in the
> same change with the ephemeral cases, and probably it's an unacceptable
> API change.

I agree.  I hadn't realized SOCK_CLOEXEC could have this sort of impact;
I'd started out from misunderstanding the goal stated in the bug report,
of having *all* sockets created with SOCK_CLOEXEC, which could be
mechanically addressed with a wrapper just like that for poll, and go to
this.

Now I guess we have to go back to the drawing board.

If the goal is to open all internal (*) sockets with SOCK_CLOEXEC
atomically, or fail, it will take some actual review of the various
hunks in my patch, but we can do without a wrapper and just add
SOCK_CLOEXEC to the socket calls proper.

If the goal is to attempt to set the CLOEXEC flag in all internal (*)
sockets as soon as possible, but to tolerate failures to set the flag,
then something similar to the wrapper I proposed would do.

If it's something else, I suppose it might take yet another different
approach.

(*) internal meaning not intentionally exposed to users, so that adding
CLOEXEC will not amount to an API change.  “Intentionally” because
ultimately all fds are directly accessible by users.

> This one is OK as far as being a proper ephemeral case, but I'd still be
> inclined just not to touch any sunrpc/ code at all.

'k
  
Alexandre Oliva Dec. 16, 2014, 6:31 p.m. UTC | #7
On Dec 11, 2014, Ondřej Bílka <neleai@seznam.cz> wrote:

> On Tue, Dec 09, 2014 at 03:53:46PM -0200, Alexandre Oliva wrote:
>> On Nov 14, 2014, Alexandre Oliva <aoliva@redhat.com> wrote:
>> 
>> > Here's a revised patch that moves __sock_cloexec to its own header,
>> > dropping the __need* ugliness that had been introduced to fix the mutual
>> > inclusion of headers.  How's this?
>> 
>> Ping?
>> https://sourceware.org/ml/libc-alpha/2014-11/msg00335.html
>> 
> Its ok from code perspective, but only internal sockets could use
> CLOEXEC.

*nod*.  I'll have to review the patch under that light.
  

Patch

diff --git a/include/socket-cloexec.h b/include/socket-cloexec.h
new file mode 100644
index 0000000..ac6a285
--- /dev/null
+++ b/include/socket-cloexec.h
@@ -0,0 +1,69 @@ 
+/* 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 <kernel-features.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.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)
+{
+  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);
+
+#ifdef FD_CLOEXEC
+  if (ret != -1)
+    {
+      int flags = __fcntl (ret, F_GETFD, 0);
+      if (flags == -1
+	  || __fcntl (ret, F_SETFD, flags | FD_CLOEXEC) == -1)
+	{
+	  __close (ret);
+	  ret = -1;
+	  errno = EINVAL;
+	}
+    }
+#endif /* FD_CLOEXEC */
+
+  return ret;
+}
+
+#pragma poison __socket
+#pragma poison socket
+
+#endif /* _SOCKET_CLOEXEC_H */
diff --git a/nscd/gai.c b/nscd/gai.c
index c159c0b..5661c54 100644
--- a/nscd/gai.c
+++ b/nscd/gai.c
@@ -38,6 +38,7 @@ 
 #include <getaddrinfo.c>
 
 /* Support code.  */
+#include <socket/have_sock_cloexec.c>
 #include <check_pf.c>
 #include <check_native.c>
 #ifdef HAVE_LIBIDN
diff --git a/posix/tst-rfc3484-2.c b/posix/tst-rfc3484-2.c
index ee92813..4701226 100644
--- a/posix/tst-rfc3484-2.c
+++ b/posix/tst-rfc3484-2.c
@@ -1,86 +1,8 @@ 
-#include <stdbool.h>
-#include <stdio.h>
-#include <ifaddrs.h>
-#include <stdint.h>
-
-/* Internal definitions used in the libc code.  */
-#define __getservbyname_r getservbyname_r
-#define __socket socket
-#define __getsockname getsockname
-#define __inet_aton inet_aton
-#define __gethostbyaddr_r gethostbyaddr_r
-#define __gethostbyname2_r gethostbyname2_r
-#define __qsort_r qsort_r
-
-void
-attribute_hidden
-__check_pf (bool *p1, bool *p2, struct in6addrinfo **in6ai, size_t *in6ailen)
-{
-  *p1 = *p2 = true;
-  *in6ai = NULL;
-  *in6ailen = 0;
-}
-
-void
-attribute_hidden
-__free_in6ai (struct in6addrinfo *ai)
-{
-}
-
-void
-attribute_hidden
-__check_native (uint32_t a1_index, int *a1_native,
-		uint32_t a2_index, int *a2_native)
-{
-}
-
-int
-attribute_hidden
-__idna_to_ascii_lz (const char *input, char **output, int flags)
-{
-  return 0;
-}
-
-int
-attribute_hidden
-__idna_to_unicode_lzlz (const char *input, char **output, int flags)
-{
-  *output = NULL;
-  return 0;
-}
-
-void
-attribute_hidden
-_res_hconf_init (void)
-{
-}
-
-#undef	USE_NSCD
-#include "../sysdeps/posix/getaddrinfo.c"
-
-service_user *__nss_hosts_database attribute_hidden;
-
+#include "tst-rfc3484.h"
 
 /* This is the beginning of the real test code.  The above defines
    (among other things) the function rfc3484_sort.  */
 
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define h(n) n
-#else
-# define h(n) __bswap_constant_32 (n)
-#endif
-
-
-ssize_t
-__getline (char **lineptr, size_t *n, FILE *s)
-{
-  *lineptr = NULL;
-  *n = 0;
-  return 0;
-}
-
-
 static int
 do_test (void)
 {
diff --git a/posix/tst-rfc3484-3.c b/posix/tst-rfc3484-3.c
index c987366..e41a649 100644
--- a/posix/tst-rfc3484-3.c
+++ b/posix/tst-rfc3484-3.c
@@ -1,76 +1,8 @@ 
-#include <stdbool.h>
-#include <stdio.h>
-#include <ifaddrs.h>
-#include <stdint.h>
-
-/* Internal definitions used in the libc code.  */
-#define __getservbyname_r getservbyname_r
-#define __socket socket
-#define __getsockname getsockname
-#define __inet_aton inet_aton
-#define __gethostbyaddr_r gethostbyaddr_r
-#define __gethostbyname2_r gethostbyname2_r
-#define __qsort_r qsort_r
-
-void
-attribute_hidden
-__check_pf (bool *p1, bool *p2, struct in6addrinfo **in6ai, size_t *in6ailen)
-{
-  *p1 = *p2 = true;
-  *in6ai = NULL;
-  *in6ailen = 0;
-}
-
-void
-attribute_hidden
-__free_in6ai (struct in6addrinfo *ai)
-{
-}
-
-void
-attribute_hidden
-__check_native (uint32_t a1_index, int *a1_native,
-		uint32_t a2_index, int *a2_native)
-{
-}
-
-int
-attribute_hidden
-__idna_to_ascii_lz (const char *input, char **output, int flags)
-{
-  return 0;
-}
-
-int
-attribute_hidden
-__idna_to_unicode_lzlz (const char *input, char **output, int flags)
-{
-  *output = NULL;
-  return 0;
-}
-
-void
-attribute_hidden
-_res_hconf_init (void)
-{
-}
-
-#undef	USE_NSCD
-#include "../sysdeps/posix/getaddrinfo.c"
-
-service_user *__nss_hosts_database attribute_hidden;
-
+#include "tst-rfc3484.h"
 
 /* This is the beginning of the real test code.  The above defines
    (among other things) the function rfc3484_sort.  */
 
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define h(n) n
-#else
-# define h(n) __bswap_constant_32 (n)
-#endif
-
 struct sockaddr_in addrs[] =
 {
   { .sin_family = AF_INET, .sin_addr = { h (0xa0a86d1d) } },
@@ -102,16 +34,6 @@  static const struct scopeentry new_scopes[] =
     { { { 0, 0, 0, 0 } }, h (0x00000000), 14 }
   };
 
-
-ssize_t
-__getline (char **lineptr, size_t *n, FILE *s)
-{
-  *lineptr = NULL;
-  *n = 0;
-  return 0;
-}
-
-
 static int
 do_test (void)
 {
diff --git a/posix/tst-rfc3484.c b/posix/tst-rfc3484.c
index 73c4dff..0c6de89 100644
--- a/posix/tst-rfc3484.c
+++ b/posix/tst-rfc3484.c
@@ -1,76 +1,8 @@ 
-#include <stdbool.h>
-#include <stdio.h>
-#include <ifaddrs.h>
-#include <stdint.h>
-
-/* Internal definitions used in the libc code.  */
-#define __getservbyname_r getservbyname_r
-#define __socket socket
-#define __getsockname getsockname
-#define __inet_aton inet_aton
-#define __gethostbyaddr_r gethostbyaddr_r
-#define __gethostbyname2_r gethostbyname2_r
-#define __qsort_r qsort_r
-
-void
-attribute_hidden
-__check_pf (bool *p1, bool *p2, struct in6addrinfo **in6ai, size_t *in6ailen)
-{
-  *p1 = *p2 = true;
-  *in6ai = NULL;
-  *in6ailen = 0;
-}
-
-void
-attribute_hidden
-__free_in6ai (struct in6addrinfo *ai)
-{
-}
-
-void
-attribute_hidden
-__check_native (uint32_t a1_index, int *a1_native,
-		uint32_t a2_index, int *a2_native)
-{
-}
-
-int
-attribute_hidden
-__idna_to_ascii_lz (const char *input, char **output, int flags)
-{
-  return 0;
-}
-
-int
-attribute_hidden
-__idna_to_unicode_lzlz (const char *input, char **output, int flags)
-{
-  *output = NULL;
-  return 0;
-}
-
-void
-attribute_hidden
-_res_hconf_init (void)
-{
-}
-
-#undef	USE_NSCD
-#include "../sysdeps/posix/getaddrinfo.c"
-
-service_user *__nss_hosts_database attribute_hidden;
-
+#include "tst-rfc3484.h"
 
 /* This is the beginning of the real test code.  The above defines
    (among other things) the function rfc3484_sort.  */
 
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define h(n) n
-#else
-# define h(n) __bswap_constant_32 (n)
-#endif
-
 struct sockaddr_in addrs[] =
 {
   { .sin_family = AF_INET, .sin_addr = { h (0x0aa85f19) } },
@@ -94,16 +26,6 @@  static int expected[naddrs] =
     9, 4, 3, 6, 5, 7, 8, 2, 0, 1
   };
 
-
-ssize_t
-__getline (char **lineptr, size_t *n, FILE *s)
-{
-  *lineptr = NULL;
-  *n = 0;
-  return 0;
-}
-
-
 static int
 do_test (void)
 {
diff --git a/posix/tst-rfc3484.h b/posix/tst-rfc3484.h
new file mode 100644
index 0000000..33c2d9c
--- /dev/null
+++ b/posix/tst-rfc3484.h
@@ -0,0 +1,77 @@ 
+/* Internal definitions used in the libc code.  */
+#define __getservbyname_r getservbyname_r
+#define __socket socket
+#define __getsockname getsockname
+#define __inet_aton inet_aton
+#define __gethostbyaddr_r gethostbyaddr_r
+#define __gethostbyname2_r gethostbyname2_r
+#define __qsort_r qsort_r
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <ifaddrs.h>
+#include <stdint.h>
+
+#include "../socket/have_sock_cloexec.c"
+
+void
+attribute_hidden
+__check_pf (bool *p1, bool *p2, struct in6addrinfo **in6ai, size_t *in6ailen)
+{
+  *p1 = *p2 = true;
+  *in6ai = NULL;
+  *in6ailen = 0;
+}
+
+void
+attribute_hidden
+__free_in6ai (struct in6addrinfo *ai)
+{
+}
+
+void
+attribute_hidden
+__check_native (uint32_t a1_index, int *a1_native,
+		uint32_t a2_index, int *a2_native)
+{
+}
+
+int
+attribute_hidden
+__idna_to_ascii_lz (const char *input, char **output, int flags)
+{
+  return 0;
+}
+
+int
+attribute_hidden
+__idna_to_unicode_lzlz (const char *input, char **output, int flags)
+{
+  *output = NULL;
+  return 0;
+}
+
+void
+attribute_hidden
+_res_hconf_init (void)
+{
+}
+
+#undef	USE_NSCD
+#include "../sysdeps/posix/getaddrinfo.c"
+
+service_user *__nss_hosts_database attribute_hidden;
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define h(n) n
+#else
+# define h(n) __bswap_constant_32 (n)
+#endif
+
+ssize_t
+__getline (char **lineptr, size_t *n, FILE *s)
+{
+  *lineptr = NULL;
+  *n = 0;
+  return 0;
+}
diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c
index b4c86227..044d3b6 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);
       if (sd < 0)
 	return;
 
diff --git a/socket/opensock.c b/socket/opensock.c
index 8dd8906..04f7e97e 100644
--- a/socket/opensock.c
+++ b/socket/opensock.c
@@ -16,7 +16,7 @@ 
    <http://www.gnu.org/licenses/>.  */
 
 #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 +32,7 @@  __opensock (void)
 
   if (sock_af != -1)
     {
-      fd = __socket (sock_af, SOCK_DGRAM, 0);
+      fd = __socket_cloexec (sock_af, SOCK_DGRAM, 0);
       if (fd != -1)
         return fd;
     }
@@ -40,28 +40,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);
 
   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);
 #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);
 #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);
 #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);
 #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);
 #endif
     }
 
diff --git a/sunrpc/clnt_tcp.c b/sunrpc/clnt_tcp.c
index f4ba0ef..bec790c 100644
--- a/sunrpc/clnt_tcp.c
+++ b/sunrpc/clnt_tcp.c
@@ -51,7 +51,7 @@ 
 #include <libintl.h>
 #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 +146,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);
       (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 40eb269..1726303 100644
--- a/sunrpc/clnt_unix.c
+++ b/sunrpc/clnt_unix.c
@@ -52,7 +52,7 @@ 
 #include <rpc/rpc.h>
 #include <sys/uio.h>
 #include <poll-noeintr.h>
-#include <sys/socket.h>
+#include <socket-cloexec.h>
 #include <rpc/pmap_clnt.h>
 #include <wchar.h>
 
@@ -132,7 +132,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);
       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 d9df0cc..b5d2ae8 100644
--- a/sunrpc/pm_getport.c
+++ b/sunrpc/pm_getport.c
@@ -37,7 +37,7 @@ 
 #include <rpc/rpc.h>
 #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 +48,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);
   if (so < 0)
     return -1;
 
diff --git a/sunrpc/pmap_rmt.c b/sunrpc/pmap_rmt.c
index fd8de85..6be7b37 100644
--- a/sunrpc/pmap_rmt.c
+++ b/sunrpc/pmap_rmt.c
@@ -41,7 +41,7 @@ 
 #include <rpc/pmap_clnt.h>
 #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 +238,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)) < 0)
     {
       perror (_("Cannot create socket for broadcast rpc"));
       stat = RPC_CANTSEND;
diff --git a/sunrpc/rtime.c b/sunrpc/rtime.c
index 862493b..68b5bae 100644
--- a/sunrpc/rtime.c
+++ b/sunrpc/rtime.c
@@ -44,7 +44,7 @@ 
 #include <rpc/clnt.h>
 #include <sys/types.h>
 #include <poll-noeintr.h>
-#include <sys/socket.h>
+#include <socket-cloexec.h>
 #include <sys/time.h>
 #include <rpc/auth_des.h>
 #include <errno.h>
@@ -84,7 +84,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);
   if (s < 0)
     return (-1);
 
diff --git a/sunrpc/svc_tcp.c b/sunrpc/svc_tcp.c
index 2ab98dc..0d5ed03 100644
--- a/sunrpc/svc_tcp.c
+++ b/sunrpc/svc_tcp.c
@@ -57,7 +57,7 @@ 
 #include <string.h>
 #include <libintl.h>
 #include <rpc/rpc.h>
-#include <sys/socket.h>
+#include <socket-cloexec.h>
 #include <poll-noeintr.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -159,7 +159,7 @@  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)) < 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 411234a..4787b0e 100644
--- a/sunrpc/svc_udp.c
+++ b/sunrpc/svc_udp.c
@@ -54,7 +54,7 @@ 
 #include <unistd.h>
 #include <string.h>
 #include <rpc/rpc.h>
-#include <sys/socket.h>
+#include <socket-cloexec.h>
 #include <errno.h>
 #include <libintl.h>
 
@@ -132,7 +132,7 @@  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)) < 0)
 	{
 	  perror (_("svcudp_create: socket creation problem"));
 	  return (SVCXPRT *) NULL;
diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c
index cbc9891..72160a2 100644
--- a/sunrpc/svc_unix.c
+++ b/sunrpc/svc_unix.c
@@ -57,7 +57,7 @@ 
 #include <string.h>
 #include <rpc/rpc.h>
 #include <rpc/svc.h>
-#include <sys/socket.h>
+#include <socket-cloexec.h>
 #include <sys/uio.h>
 #include <poll-noeintr.h>
 #include <errno.h>
@@ -157,7 +157,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)) < 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 1b8775f..2774df5 100644
--- a/sysdeps/gnu/ifaddrs.c
+++ b/sysdeps/gnu/ifaddrs.c
@@ -18,7 +18,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 +37,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);
   struct ifreq *ifreqs;
   int nifs;
 
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 31bb7e6..fa21de4 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -51,7 +51,7 @@  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <arpa/inet.h>
 #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 +2512,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);
 		}
 	      else
 		{
diff --git a/sysdeps/unix/sysv/linux/check_native.c b/sysdeps/unix/sysv/linux/check_native.c
index 68adeb8..e85b8de 100644
--- a/sysdeps/unix/sysv/linux/check_native.c
+++ b/sysdeps/unix/sysv/linux/check_native.c
@@ -28,6 +28,7 @@ 
 #include <net/if.h>
 #include <net/if_arp.h>
 #include <sys/ioctl.h>
+#include <socket-cloexec.h>
 
 #include <asm/types.h>
 #include <linux/netlink.h>
@@ -40,7 +41,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);
 
   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 976f249e..4930973 100644
--- a/sysdeps/unix/sysv/linux/check_pf.c
+++ b/sysdeps/unix/sysv/linux/check_pf.c
@@ -25,7 +25,7 @@ 
 #include <time.h>
 #include <unistd.h>
 #include <stdint.h>
-#include <sys/socket.h>
+#include <socket-cloexec.h>
 
 #include <asm/types.h>
 #include <linux/netlink.h>
@@ -353,7 +353,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);
 
       if (__glibc_likely (fd >= 0))
 	{
diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c
index a47b2ed..06e4a65 100644
--- a/sysdeps/unix/sysv/linux/ifaddrs.c
+++ b/sysdeps/unix/sysv/linux/ifaddrs.c
@@ -28,7 +28,7 @@ 
 #include <stdlib.h>
 #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 +251,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);
   if (h->fd < 0)
     goto out;