93dc2d
commit ad615b59c78d6d37fee921fb2b2ae6b72c930625
93dc2d
Author: Florian Weimer <fweimer@redhat.com>
93dc2d
Date:   Tue Sep 28 18:55:49 2021 +0200
93dc2d
93dc2d
    Linux: Simplify __opensock and fix race condition [BZ #28353]
93dc2d
    
93dc2d
    AF_NETLINK support is not quite optional on modern Linux systems
93dc2d
    anymore, so it is likely that the first attempt will always succeed.
93dc2d
    Consequently, there is no need to cache the result.  Keep AF_UNIX
93dc2d
    and the Internet address families as a fallback, for the rare case
93dc2d
    that AF_NETLINK is missing.  The other address families previously
93dc2d
    probed are totally obsolete be now, so remove them.
93dc2d
    
93dc2d
    Use this simplified version as the generic implementation, disabling
93dc2d
    Netlink support as needed.
93dc2d
    
93dc2d
    (cherry picked from commit 5bf07e1b3a74232bfb8332275110be1a5da50f83)
93dc2d
93dc2d
diff --git a/socket/opensock.c b/socket/opensock.c
93dc2d
index 37148d4743343ff4..ff94d27a61bd3889 100644
93dc2d
--- a/socket/opensock.c
93dc2d
+++ b/socket/opensock.c
93dc2d
@@ -1,4 +1,5 @@
93dc2d
-/* Copyright (C) 1999-2021 Free Software Foundation, Inc.
93dc2d
+/* Create socket with an unspecified address family for use with ioctl.
93dc2d
+   Copyright (C) 1999-2021 Free Software Foundation, Inc.
93dc2d
    This file is part of the GNU C Library.
93dc2d
 
93dc2d
    The GNU C Library is free software; you can redistribute it and/or
93dc2d
@@ -15,56 +16,34 @@
93dc2d
    License along with the GNU C Library; if not, see
93dc2d
    <https://www.gnu.org/licenses/>.  */
93dc2d
 
93dc2d
-#include <stdio.h>
93dc2d
+#include <errno.h>
93dc2d
 #include <sys/socket.h>
93dc2d
-#include <libc-lock.h>
93dc2d
 
93dc2d
 /* Return a socket of any type.  The socket can be used in subsequent
93dc2d
    ioctl calls to talk to the kernel.  */
93dc2d
 int
93dc2d
 __opensock (void)
93dc2d
 {
93dc2d
-  /* Cache the last AF that worked, to avoid many redundant calls to
93dc2d
-     socket().  */
93dc2d
-  static int sock_af = -1;
93dc2d
-  int fd = -1;
93dc2d
-  __libc_lock_define_initialized (static, lock);
93dc2d
-
93dc2d
-  if (sock_af != -1)
93dc2d
-    {
93dc2d
-      fd = __socket (sock_af, SOCK_DGRAM, 0);
93dc2d
-      if (fd != -1)
93dc2d
-        return fd;
93dc2d
-    }
93dc2d
-
93dc2d
-  __libc_lock_lock (lock);
93dc2d
-
93dc2d
-  if (sock_af != -1)
93dc2d
-    fd = __socket (sock_af, SOCK_DGRAM, 0);
93dc2d
-
93dc2d
-  if (fd == -1)
93dc2d
-    {
93dc2d
-#ifdef AF_INET
93dc2d
-      fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
93dc2d
-#endif
93dc2d
-#ifdef AF_INET6
93dc2d
-      if (fd < 0)
93dc2d
-	fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
93dc2d
-#endif
93dc2d
-#ifdef AF_IPX
93dc2d
-      if (fd < 0)
93dc2d
-	fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0);
93dc2d
-#endif
93dc2d
-#ifdef AF_AX25
93dc2d
-      if (fd < 0)
93dc2d
-	fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0);
93dc2d
-#endif
93dc2d
-#ifdef AF_APPLETALK
93dc2d
-      if (fd < 0)
93dc2d
-	fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0);
93dc2d
+  /* SOCK_DGRAM is supported by all address families.  (Netlink does
93dc2d
+     not support SOCK_STREAM.)  */
93dc2d
+  int type = SOCK_DGRAM | SOCK_CLOEXEC;
93dc2d
+  int fd;
93dc2d
+
93dc2d
+#ifdef AF_NETLINK
93dc2d
+  fd = __socket (AF_NETLINK, type, 0);
93dc2d
+  if (fd >= 0)
93dc2d
+    return fd;
93dc2d
 #endif
93dc2d
-    }
93dc2d
 
93dc2d
-  __libc_lock_unlock (lock);
93dc2d
+  fd = __socket (AF_UNIX, type, 0);
93dc2d
+  if (fd >= 0)
93dc2d
+    return fd;
93dc2d
+  fd = __socket (AF_INET, type, 0);
93dc2d
+  if (fd >= 0)
93dc2d
+    return fd;
93dc2d
+  fd = __socket (AF_INET6, type, 0);
93dc2d
+  if (fd >= 0)
93dc2d
+    return fd;
93dc2d
+  __set_errno (ENOENT);
93dc2d
   return fd;
93dc2d
 }
93dc2d
diff --git a/sysdeps/unix/sysv/linux/opensock.c b/sysdeps/unix/sysv/linux/opensock.c
93dc2d
deleted file mode 100644
93dc2d
index e87d6e58b0b84f82..0000000000000000
93dc2d
--- a/sysdeps/unix/sysv/linux/opensock.c
93dc2d
+++ /dev/null
93dc2d
@@ -1,114 +0,0 @@
93dc2d
-/* Copyright (C) 1999-2021 Free Software Foundation, Inc.
93dc2d
-   This file is part of the GNU C Library.
93dc2d
-
93dc2d
-   The GNU C Library is free software; you can redistribute it and/or
93dc2d
-   modify it under the terms of the GNU Lesser General Public
93dc2d
-   License as published by the Free Software Foundation; either
93dc2d
-   version 2.1 of the License, or (at your option) any later version.
93dc2d
-
93dc2d
-   The GNU C Library is distributed in the hope that it will be useful,
93dc2d
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
93dc2d
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
93dc2d
-   Lesser General Public License for more details.
93dc2d
-
93dc2d
-   You should have received a copy of the GNU Lesser General Public
93dc2d
-   License along with the GNU C Library; if not, see
93dc2d
-   <https://www.gnu.org/licenses/>.  */
93dc2d
-
93dc2d
-#include <assert.h>
93dc2d
-#include <errno.h>
93dc2d
-#include <stdio.h>
93dc2d
-#include <string.h>
93dc2d
-#include <unistd.h>
93dc2d
-#include <sys/socket.h>
93dc2d
-
93dc2d
-/* Return a socket of any type.  The socket can be used in subsequent
93dc2d
-   ioctl calls to talk to the kernel.  */
93dc2d
-int
93dc2d
-__opensock (void)
93dc2d
-{
93dc2d
-  static int last_family;	/* Available socket family we will use.  */
93dc2d
-  static int last_type;
93dc2d
-  static const struct
93dc2d
-  {
93dc2d
-    int family;
93dc2d
-    const char procname[15];
93dc2d
-  } afs[] =
93dc2d
-    {
93dc2d
-      { AF_UNIX, "net/unix" },
93dc2d
-      { AF_INET, "" },
93dc2d
-      { AF_INET6, "net/if_inet6" },
93dc2d
-      { AF_AX25, "net/ax25" },
93dc2d
-      { AF_NETROM, "net/nr" },
93dc2d
-      { AF_ROSE, "net/rose" },
93dc2d
-      { AF_IPX, "net/ipx" },
93dc2d
-      { AF_APPLETALK, "net/appletalk" },
93dc2d
-      { AF_ECONET, "sys/net/econet" },
93dc2d
-      { AF_ASH, "sys/net/ash" },
93dc2d
-      { AF_X25, "net/x25" },
93dc2d
-#ifdef NEED_AF_IUCV
93dc2d
-      { AF_IUCV, "net/iucv" }
93dc2d
-#endif
93dc2d
-    };
93dc2d
-#define nafs (sizeof (afs) / sizeof (afs[0]))
93dc2d
-  char fname[sizeof "/proc/" + 14];
93dc2d
-  int result;
93dc2d
-  int has_proc;
93dc2d
-  size_t cnt;
93dc2d
-
93dc2d
-  /* We already know which family to use from the last call.  Use it
93dc2d
-     again.  */
93dc2d
-  if (last_family != 0)
93dc2d
-    {
93dc2d
-      assert (last_type != 0);
93dc2d
-
93dc2d
-      result = __socket (last_family, last_type | SOCK_CLOEXEC, 0);
93dc2d
-      if (result != -1 || errno != EAFNOSUPPORT)
93dc2d
-	/* Maybe the socket type isn't supported anymore (module is
93dc2d
-	   unloaded).  In this case again try to find the type.  */
93dc2d
-	return result;
93dc2d
-
93dc2d
-      /* Reset the values.  They seem not valid anymore.  */
93dc2d
-      last_family = 0;
93dc2d
-      last_type = 0;
93dc2d
-    }
93dc2d
-
93dc2d
-  /* Check whether the /proc filesystem is available.  */
93dc2d
-  has_proc = __access ("/proc/net", R_OK) != -1;
93dc2d
-  strcpy (fname, "/proc/");
93dc2d
-
93dc2d
-  /* Iterate over the interface families and find one which is
93dc2d
-     available.  */
93dc2d
-  for (cnt = 0; cnt < nafs; ++cnt)
93dc2d
-    {
93dc2d
-      int type = SOCK_DGRAM;
93dc2d
-
93dc2d
-      if (has_proc && afs[cnt].procname[0] != '\0')
93dc2d
-	{
93dc2d
-	  strcpy (fname + 6, afs[cnt].procname);
93dc2d
-	  if (__access (fname, R_OK) == -1)
93dc2d
-	    /* The /proc entry is not available.  I.e., we cannot
93dc2d
-	       create a socket of this type (without loading the
93dc2d
-	       module).  Don't look for it since this might trigger
93dc2d
-	       loading the module.  */
93dc2d
-	    continue;
93dc2d
-	}
93dc2d
-
93dc2d
-      if (afs[cnt].family == AF_NETROM || afs[cnt].family == AF_X25)
93dc2d
-	type = SOCK_SEQPACKET;
93dc2d
-
93dc2d
-      result = __socket (afs[cnt].family, type | SOCK_CLOEXEC, 0);
93dc2d
-      if (result != -1)
93dc2d
-	{
93dc2d
-	  /* Found an available family.  */
93dc2d
-	  last_type = type;
93dc2d
-	  last_family = afs[cnt].family;
93dc2d
-	  return result;
93dc2d
-	}
93dc2d
-    }
93dc2d
-
93dc2d
-  /* None of the protocol families is available.  It is unclear what kind
93dc2d
-     of error is returned.  ENOENT seems like a reasonable choice.  */
93dc2d
-  __set_errno (ENOENT);
93dc2d
-  return -1;
93dc2d
-}
93dc2d
diff --git a/sysdeps/unix/sysv/linux/s390/opensock.c b/sysdeps/unix/sysv/linux/s390/opensock.c
93dc2d
deleted file mode 100644
93dc2d
index f099d651ff04d211..0000000000000000
93dc2d
--- a/sysdeps/unix/sysv/linux/s390/opensock.c
93dc2d
+++ /dev/null
93dc2d
@@ -1,2 +0,0 @@
93dc2d
-#define NEED_AF_IUCV 1
93dc2d
-#include "../opensock.c"