|
|
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"
|