From patchwork Wed May 5 21:41:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 43263 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 12A4138618CC; Wed, 5 May 2021 21:41:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 12A4138618CC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1620250918; bh=KcuZCXuT0hEIjBotVqF9XdxS65jLQhAB8CKKYlQrXKU=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Qz8DsdktchJ9/eFiRV00ufBSfKvOGQ0mzRnNzOdFBIxBBtd7f6npxFw15qNlJsn3P Ng2Ov6hdySTNTmxt/x0+4SVpEQsGitRgm1elH0/e88Fcz7CJXFTCbATVQWIjJa+gew pZPcOuf9HHTiGcw00n23NKhpNzoCCzYFb+zHt+6A= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x730.google.com (mail-qk1-x730.google.com [IPv6:2607:f8b0:4864:20::730]) by sourceware.org (Postfix) with ESMTPS id 95FE83860C39 for ; Wed, 5 May 2021 21:41:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 95FE83860C39 Received: by mail-qk1-x730.google.com with SMTP id o27so3095637qkj.9 for ; Wed, 05 May 2021 14:41:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KcuZCXuT0hEIjBotVqF9XdxS65jLQhAB8CKKYlQrXKU=; b=ozhqg9pukExMwW8MC1vCb3m0N4BpHp5ddneK8m/YPp+3xQeaCkkmYmD0rJLlWBjZoG QMcrZar2bNhETVPQPFUpxV/VBcEHDAxQH5wTU/4R2jeI7EBhmi7WSz1QAnm7XtpBQKcG zNibnI8mLtAmizchNq9DjSsrpoISA3nnHuhOCwsrPEVt72L0zKkZjrO3Q5pnBxle8jll mVAf3ABpc5RjYgJIL/AKYKR9pvQQ23E9dICXL3B+5hJKzcY4C9UVjNlJM9ifTLuVTCt3 HjsuGYdwhRSRdwp1UpqpQAqTK/WPveAqG9csVWWqqK3S2CVhQE7q4HTfb05ubhtkLPMq njlA== X-Gm-Message-State: AOAM5336QibcSMDZwZ3dI1n5ZY3+tgNlPoTczA8o2yhLuIvsihzqEbi6 XiZZlTo1mluvV1EI86VgOYkuywfCbt76KA== X-Google-Smtp-Source: ABdhPJxYuPuCgLzrPq6aqj9P4Zcukp7xNb56mGvig80duJi4VWuC4nPjcoCbDlY2hmg5qTddBPvrxw== X-Received: by 2002:a37:9e44:: with SMTP id h65mr854289qke.297.1620250911893; Wed, 05 May 2021 14:41:51 -0700 (PDT) Received: from birita.. ([177.194.37.86]) by smtp.googlemail.com with ESMTPSA id t9sm466146qkg.121.2021.05.05.14.41.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 May 2021 14:41:51 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v5 4/5] io: Add closefrom [BZ #10353] Date: Wed, 5 May 2021 18:41:42 -0300 Message-Id: <20210505214143.3649585-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210505214143.3649585-1-adhemerval.zanella@linaro.org> References: <20210505214143.3649585-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Changes from v4: * Rebased against master. --- The function closes all open file descriptors greater than or equal to input argument. Negative values are clamped to 0, i.e, it will close all file descriptors. As indicated by the bug report, this is a common symbol provided by different systems (Solaris, OpenBSD, NetBSD, FreeBSD) and, although its has inherent issues with not taking in consideration internal libc file descriptors (such as syslog), this is also a common feature used in multiple projects [1][2][3][4][5]. The Linux fallback implementation iterates over /proc and close all file descriptors sequentially, and issues a lseek after a file descriptor is closed after a getdents calls. Also, the interface is set a fail-safe meaning that a failure in the fallback results in a process abort. Checked on x86_64-linux-gnu on kernel v5.11 and v5.4. [1] https://github.com/systemd/systemd/blob/5238e9575906297608ff802a27e2ff9effa3b338/src/basic/fd-util.c#L217 [2] https://github.com/lxc/lxc/blob/ddf4b77e11a4d08f09b7b9cd13e593f8c047edc5/src/lxc/start.c#L236 [3] https://github.com/python/cpython/blob/9e4f2f3a6b8ee995c365e86d976937c141d867f8/Modules/_posixsubprocess.c#L220 [4] https://github.com/rust-lang/rust/blob/5f47c0613ed4eb46fca3633c1297364c09e5e451/src/libstd/sys/unix/process2.rs#L303-L308 [5] https://github.com/openjdk/jdk/blob/master/src/java.base/unix/native/libjava/childproc.c#L82 --- NEWS | 4 + include/unistd.h | 1 + io/Makefile | 4 +- io/Versions | 3 + io/closefrom.c | 34 ++++ io/tst-closefrom.c | 152 ++++++++++++++++++ manual/llio.texi | 10 ++ posix/unistd.h | 6 + sysdeps/mach/hurd/i386/libc.abilist | 1 + sysdeps/unix/sysv/linux/Makefile | 3 +- sysdeps/unix/sysv/linux/aarch64/libc.abilist | 1 + sysdeps/unix/sysv/linux/alpha/libc.abilist | 1 + sysdeps/unix/sysv/linux/arc/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/le/libc.abilist | 1 + sysdeps/unix/sysv/linux/closefrom.c | 35 ++++ sysdeps/unix/sysv/linux/closefrom_fallback.c | 97 +++++++++++ sysdeps/unix/sysv/linux/csky/libc.abilist | 1 + sysdeps/unix/sysv/linux/hppa/libc.abilist | 1 + sysdeps/unix/sysv/linux/i386/libc.abilist | 1 + sysdeps/unix/sysv/linux/ia64/libc.abilist | 1 + .../sysv/linux/m68k/coldfire/libc.abilist | 1 + .../unix/sysv/linux/m68k/m680x0/libc.abilist | 1 + .../sysv/linux/microblaze/be/libc.abilist | 1 + .../sysv/linux/microblaze/le/libc.abilist | 1 + .../sysv/linux/mips/mips32/fpu/libc.abilist | 1 + .../sysv/linux/mips/mips32/nofpu/libc.abilist | 1 + .../sysv/linux/mips/mips64/n32/libc.abilist | 1 + .../sysv/linux/mips/mips64/n64/libc.abilist | 1 + sysdeps/unix/sysv/linux/nios2/libc.abilist | 1 + .../linux/powerpc/powerpc32/fpu/libc.abilist | 1 + .../powerpc/powerpc32/nofpu/libc.abilist | 1 + .../linux/powerpc/powerpc64/be/libc.abilist | 1 + .../linux/powerpc/powerpc64/le/libc.abilist | 1 + .../unix/sysv/linux/riscv/rv32/libc.abilist | 1 + .../unix/sysv/linux/riscv/rv64/libc.abilist | 1 + .../unix/sysv/linux/s390/s390-32/libc.abilist | 1 + .../unix/sysv/linux/s390/s390-64/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/le/libc.abilist | 1 + .../sysv/linux/sparc/sparc32/libc.abilist | 1 + .../sysv/linux/sparc/sparc64/libc.abilist | 1 + .../unix/sysv/linux/x86_64/64/libc.abilist | 1 + .../unix/sysv/linux/x86_64/x32/libc.abilist | 1 + 44 files changed, 380 insertions(+), 2 deletions(-) create mode 100644 io/closefrom.c create mode 100644 io/tst-closefrom.c create mode 100644 sysdeps/unix/sysv/linux/closefrom.c create mode 100644 sysdeps/unix/sysv/linux/closefrom_fallback.c diff --git a/NEWS b/NEWS index c151c4b293..d4506f5f4b 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,10 @@ Major new features: * On Linux, the close_range function has been added. It allows efficiently closing a range of file descriptors on recent kernels (version 5.9). +* The function closefrom has been added. It closes all file descriptors + greater than given integer. This function is a GNU extension, although it + also present in other systems. + Deprecated and removed features, and other changes affecting compatibility: * The function pthread_mutex_consistent_np has been deprecated; programs diff --git a/include/unistd.h b/include/unistd.h index 1363976161..c596c6fb24 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -152,6 +152,7 @@ extern int __brk (void *__addr) attribute_hidden; extern int __close (int __fd); libc_hidden_proto (__close) extern int __libc_close (int __fd); +extern _Bool __closefrom_fallback (int __lowfd) attribute_hidden; extern ssize_t __read (int __fd, void *__buf, size_t __nbytes); libc_hidden_proto (__read) extern ssize_t __write (int __fd, const void *__buf, size_t __n); diff --git a/io/Makefile b/io/Makefile index a22492f3f3..d574feb3f0 100644 --- a/io/Makefile +++ b/io/Makefile @@ -54,7 +54,8 @@ routines := \ posix_fadvise posix_fadvise64 \ posix_fallocate posix_fallocate64 \ sendfile sendfile64 copy_file_range \ - utimensat futimens file_change_detection + utimensat futimens file_change_detection \ + closefrom others := pwd test-srcs := ftwtest @@ -75,6 +76,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ tst-lutimes \ tst-futimens \ tst-utimensat \ + tst-closefrom \ # Likewise for statx, but we do not need static linking here. tests-internal += tst-statx diff --git a/io/Versions b/io/Versions index 49c4d2d40a..f28bd43773 100644 --- a/io/Versions +++ b/io/Versions @@ -136,6 +136,9 @@ libc { stat; stat64; fstat; fstat64; lstat; lstat64; fstatat; fstatat64; mknod; mknodat; } + GLIBC_2.34 { + closefrom; + } GLIBC_PRIVATE { __libc_fcntl64; __fcntl_nocancel; diff --git a/io/closefrom.c b/io/closefrom.c new file mode 100644 index 0000000000..01660a7531 --- /dev/null +++ b/io/closefrom.c @@ -0,0 +1,34 @@ +/* Close a range of file descriptors. + Copyright (C) 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 + . */ + +#include +#include +#include + +void +__closefrom (int lowfd) +{ + int maxfd = __getdtablesize (); + if (maxfd == -1) + __fortify_fail ("closefrom failed to get the file descriptor table size"); + + for (int i = 0; i < maxfd; i++) + if (i >= lowfd) + __close_nocancel_nostatus (i); +} +weak_alias (__closefrom, closefrom) diff --git a/io/tst-closefrom.c b/io/tst-closefrom.c new file mode 100644 index 0000000000..d4c187073c --- /dev/null +++ b/io/tst-closefrom.c @@ -0,0 +1,152 @@ +/* Smoke test for the closefrom. + Copyright (C) 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 + . */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define NFDS 100 + +static int +open_multiple_temp_files (void) +{ + /* Check if the temporary file descriptor has no no gaps. */ + int lowfd = xopen ("/dev/null", O_RDONLY, 0600); + for (int i = 1; i <= NFDS; i++) + TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), lowfd + i); + return lowfd; +} + +static int +closefrom_test (void) +{ + struct support_descriptors *descrs = support_descriptors_list (); + + int lowfd = open_multiple_temp_files (); + + const int maximum_fd = lowfd + NFDS; + const int half_fd = lowfd + NFDS / 2; + const int gap = maximum_fd / 4; + + /* Close half of the descriptors and check result. */ + closefrom (half_fd); + + for (int i = half_fd; i <= maximum_fd; i++) + { + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } + for (int i = 0; i < half_fd; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Create some gaps, close up to a threshold, and check result. */ + xclose (lowfd + 35); + xclose (lowfd + 38); + xclose (lowfd + 42); + xclose (lowfd + 46); + + /* Close half of the descriptors and check result. */ + closefrom (gap); + for (int i = gap + 1; i < maximum_fd; i++) + { + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } + for (int i = 0; i < gap; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Close the remmaining but the last one. */ + closefrom (lowfd + 1); + for (int i = lowfd + 1; i <= maximum_fd; i++) + { + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } + TEST_VERIFY (fcntl (lowfd, F_GETFL) > -1); + + /* Close the last one. */ + closefrom (lowfd); + TEST_COMPARE (fcntl (lowfd, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + + /* Double check by check the /proc. */ + support_descriptors_check (descrs); + support_descriptors_free (descrs); + + return 0; +} + +/* Check if closefrom works even when no new file descriptors can be + created. */ +static int +closefrom_test_file_desc_limit (void) +{ + int max_fd = NFDS; + { + struct rlimit rl; + if (getrlimit (RLIMIT_NOFILE, &rl) == -1) + FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m"); + + max_fd = (rl.rlim_cur < max_fd ? rl.rlim_cur : max_fd); + rl.rlim_cur = max_fd; + + if (setrlimit (RLIMIT_NOFILE, &rl) == 1) + FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m"); + } + + /* Exhauste the file descriptor limit. */ + int lowfd = xopen ("/dev/null", O_RDONLY, 0600); + for (;;) + { + int fd = open ("/dev/null", O_RDONLY, 0600); + if (fd == -1) + { + if (errno != EMFILE) + FAIL_EXIT1 ("open: %m"); + break; + } + TEST_VERIFY_EXIT (fd < max_fd); + } + + closefrom (lowfd); + for (int i = lowfd; i < NFDS; i++) + { + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } + + return 0; +} + +static int +do_test (void) +{ + closefrom_test (); + closefrom_test_file_desc_limit (); + + return 0; +} + +#include diff --git a/manual/llio.texi b/manual/llio.texi index 3613ead72c..553e455e67 100644 --- a/manual/llio.texi +++ b/manual/llio.texi @@ -328,6 +328,16 @@ The maximum number of file descriptors is controlled by the @end table @end deftypefun +@deftypefun void closefrom (int @var{lowfd}) +@standards{GNU, unistd.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} + +The function @code{closefrom} closes all file descriptors larger than or equal +to @var{lowfd} then @var{lowfd}. This function is similar to call +@code{close} applied to the specified file descriptor range. + +Already closed file descriptors are ignored. +@end deftypefun @node I/O Primitives @section Input and Output Primitives diff --git a/posix/unistd.h b/posix/unistd.h index d9d8929f71..f3f7cb99c4 100644 --- a/posix/unistd.h +++ b/posix/unistd.h @@ -357,6 +357,12 @@ extern __off64_t lseek64 (int __fd, __off64_t __offset, int __whence) __THROW. */ extern int close (int __fd); +#ifdef __USE_MISC +/* Close all open file descriptors greater than or equal to LOWFD. + Negative LOWFD is clamped to 0. */ +extern void closefrom (int __lowfd) __THROW; +#endif + /* Read NBYTES into BUF from FD. Return the number read, -1 for errors or 0 for EOF. diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist index fb2683edc2..52d9134a4e 100644 --- a/sysdeps/mach/hurd/i386/libc.abilist +++ b/sysdeps/mach/hurd/i386/libc.abilist @@ -2207,6 +2207,7 @@ GLIBC_2.33 stat64 F GLIBC_2.34 __isnanf128 F GLIBC_2.34 __libc_start_main F GLIBC_2.34 _hurd_libc_proc_init F +GLIBC_2.34 closefrom F GLIBC_2.34 execveat F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 605db4169f..6803920a6e 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -64,7 +64,8 @@ sysdep_routines += adjtimex clone umount umount2 readahead sysctl \ time64-support pselect32 \ xstat fxstat lxstat xstat64 fxstat64 lxstat64 \ fxstatat fxstatat64 \ - xmknod xmknodat + xmknod xmknodat \ + closefrom_fallback CFLAGS-gethostid.c = -fexceptions CFLAGS-tee.c = -fexceptions -fasynchronous-unwind-tables diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist index 0364c02d91..35772d07da 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2293,6 +2293,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist index fd6db54689..a51aff6089 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -2380,6 +2380,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist index 6d66c25abd..853caba0e3 100644 --- a/sysdeps/unix/sysv/linux/arc/libc.abilist +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist @@ -2052,6 +2052,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist index 34e037b66a..14ddad655b 100644 --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist @@ -189,6 +189,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist index a319d48ae7..313401c458 100644 --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist @@ -186,6 +186,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/closefrom.c b/sysdeps/unix/sysv/linux/closefrom.c new file mode 100644 index 0000000000..f5d7342c2c --- /dev/null +++ b/sysdeps/unix/sysv/linux/closefrom.c @@ -0,0 +1,35 @@ +/* Close a range of file descriptors. Linux version. + Copyright (C) 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 + . */ + +#include +#include +#include + +void +__closefrom (int lowfd) +{ + int l = MAX (0, lowfd); + + int r = __close_range (l, ~0U, 0); + if (r == 0) + return; + + if (!__closefrom_fallback (l)) + __fortify_fail ("closefrom failed to close a file descriptor"); +} +weak_alias (__closefrom, closefrom) diff --git a/sysdeps/unix/sysv/linux/closefrom_fallback.c b/sysdeps/unix/sysv/linux/closefrom_fallback.c new file mode 100644 index 0000000000..61e71d388d --- /dev/null +++ b/sysdeps/unix/sysv/linux/closefrom_fallback.c @@ -0,0 +1,97 @@ +/* Close a range of file descriptors. Linux version. + Copyright (C) 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 + . */ + +#include +#include +#include +#include + +/* Fallback code: iterates over /proc/self/fd, closing each file descriptor + that fall on the criteria. */ +_Bool +__closefrom_fallback (int from) +{ + bool ret = false; + + int dirfd = __open_nocancel (FD_TO_FILENAME_PREFIX, O_RDONLY | O_DIRECTORY, + 0); + if (dirfd == -1) + { + /* The closefrom should work even when process can't open new files. */ + if (errno == ENOENT) + goto err; + + for (int i = from; i < INT_MAX; i++) + { + int r = __close_nocancel (i); + if (r == 0 || (r == -1 && errno != EBADF)) + break; + } + + dirfd = __open_nocancel (FD_TO_FILENAME_PREFIX, O_RDONLY | O_DIRECTORY, + 0); + if (dirfd == -1) + goto err; + } + + char buffer[1024]; + while (true) + { + ssize_t ret = __getdents64 (dirfd, buffer, sizeof (buffer)); + if (ret == -1) + goto err; + else if (ret == 0) + break; + + /* If any file descriptor is closed it resets the /proc/self position + read again from the start (to obtain any possible kernel update). */ + bool closed = false; + char *begin = buffer, *end = buffer + ret; + while (begin != end) + { + unsigned short int d_reclen; + memcpy (&d_reclen, begin + offsetof (struct dirent64, d_reclen), + sizeof (d_reclen)); + const char *dname = begin + offsetof (struct dirent64, d_name); + begin += d_reclen; + + if (dname[0] == '.') + continue; + + int fd = 0; + for (const char *s = dname; (unsigned int) (*s) - '0' < 10; s++) + fd = 10 * fd + (*s - '0'); + + if (fd == dirfd || fd < from) + continue; + + /* We ignore close errors because EBADF, EINTR, and EIO means the + descriptor has been released. */ + __close_nocancel (fd); + closed = true; + } + + if (closed && __lseek (dirfd, 0, SEEK_SET) < 0) + goto err; + } + + ret = true; +err: + __close_nocancel (dirfd); + return ret; +} diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist index 2d32c1cf9b..68658e3ef8 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2236,6 +2236,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist index 1ae324809c..c16e7d8f2e 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2187,6 +2187,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist index eb7b05cca0..e73a11a8ea 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2370,6 +2370,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist index 5c275e85d0..84ee3d6243 100644 --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist @@ -2221,6 +2221,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist index 38e37fb013..297b8cab6c 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -190,6 +190,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist index b4e954bf72..c562997d51 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2313,6 +2313,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist index f93feaf16e..8fcbcfffeb 100644 --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist @@ -2287,6 +2287,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist index e992581a4b..5586d3610a 100644 --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist @@ -2284,6 +2284,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist index cb38de9f4c..3d5210a6e3 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2276,6 +2276,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist index f573edd1a8..49c1a2c30b 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2274,6 +2274,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist index 2bbd7e604d..238f2b3b21 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2282,6 +2282,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist index 7fd5172f73..244c8dab63 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2276,6 +2276,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist index 2e89b434a0..016317653c 100644 --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist @@ -2326,6 +2326,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist index 5ced3b6daa..e81d40ec43 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -2340,6 +2340,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist index e74fa1d141..33ba8522fd 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -2373,6 +2373,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist index 1435c63ce2..252a669528 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2188,6 +2188,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist index ce3466bc90..19f7bda2a2 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2489,6 +2489,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist index cb71ce0331..7bbdc8e400 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -2054,6 +2054,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist index b13248939f..94fd53fd54 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2254,6 +2254,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist index 0757e54290..43d5f17ef4 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -2338,6 +2338,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist index e2f3a42a71..418643ba2b 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -2225,6 +2225,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist index 8566ae1cb3..b88e4c1b7b 100644 --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist @@ -2194,6 +2194,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist index 90bfc6f7b3..33c1bb6555 100644 --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist @@ -2191,6 +2191,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist index 32ec7865c8..3af45b8b0e 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -2329,6 +2329,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist index 4cdbfdb13f..0cc316d932 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2242,6 +2242,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index 15fee4a8ff..5d2719da05 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2203,6 +2203,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist index 2c74a510b3..029abb00e4 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2308,6 +2308,7 @@ GLIBC_2.34 __pthread_mutex_unlock F GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 call_once F GLIBC_2.34 close_range F +GLIBC_2.34 closefrom F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F