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