From patchwork Tue Jul 6 14:58:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 44175 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 63F4B388E839 for ; Tue, 6 Jul 2021 15:12:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 63F4B388E839 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1625584346; bh=EvglTjfJLoYFYIHB9js8gh0eoeCl9L91wNByOphfOsc=; 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=mk8YFX0gnmNNOEQOutj5M4U1tQcIot+TTAdFlntzGbzLWg2pGmWYigBC9jng6uHUX WS4/VXLGOC4ZY3oOcnXodF66FaDwfoEaivGGb9ySyLPEPxoLQz8SqV4HlqTDOzBPsB ODEyUYsnX7GFXJZL7s3qjqzCeQpkiCnpyIloXhs4= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pg1-x52d.google.com (mail-pg1-x52d.google.com [IPv6:2607:f8b0:4864:20::52d]) by sourceware.org (Postfix) with ESMTPS id CE5C4388F005 for ; Tue, 6 Jul 2021 14:58:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org CE5C4388F005 Received: by mail-pg1-x52d.google.com with SMTP id y17so21612554pgf.12 for ; Tue, 06 Jul 2021 07:58:48 -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=EvglTjfJLoYFYIHB9js8gh0eoeCl9L91wNByOphfOsc=; b=EulFMdyA0WmXr2UJW4e8IwWYOFzgQzPR355iz5D1yhzrdPS5BNrm39gSVnFeWiHnNV b4BpaS7s/Re5zzYANzK2rePaL6DdZ9vdobiZWUp77Gj1DZcffbSBQk+aql7dv0vx5H6a b3Zx8etcBw0UtKYHURVwOWc+kfCzSMD4t2B8X0QrSFIEr59u63qASkK064La/k78dNIR e+CZ3PteQcZtlLNyKsaJWoIpX5jHlqVCieuXOcrAzV1WA1nVWVdHX06Ql+m5nKxahVhw oE5wS7gApmNobjae83vadDANeSEITLy2I6Vs3SGB5LOJUT3Yb3KXjCR6EictlYoKKAu9 2+Fg== X-Gm-Message-State: AOAM5313xVmwbk7+8eykrTjj8om1TooW+Cjv0WoVq9af648I/KNupi1I fdpe77AI9ODJNoP1yNYwRbfy27eRO74Lkg== X-Google-Smtp-Source: ABdhPJxnsM6nFfKYveQKtyiiAyMd112bff88PqRAiPBNmK2hp/tBmw3+hxRy9r50RZnPvNpgYbFXTQ== X-Received: by 2002:a65:6704:: with SMTP id u4mr21255108pgf.140.1625583527449; Tue, 06 Jul 2021 07:58:47 -0700 (PDT) Received: from birita.. ([177.194.59.218]) by smtp.gmail.com with ESMTPSA id n23sm19018488pgv.76.2021.07.06.07.58.46 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jul 2021 07:58:47 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v7 2/4] linux: Add close_range Date: Tue, 6 Jul 2021 11:58:37 -0300 Message-Id: <20210706145839.1658623-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210706145839.1658623-1-adhemerval.zanella@linaro.org> References: <20210706145839.1658623-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.5 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.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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 Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" Changes from previous version: - Fixed manual entry and added ENOSYS returned code. --- It was added on Linux 5.9 (278a5fbaed89) with CLOSE_RANGE_CLOEXEC added on 5.11 (582f1fb6b721f). Although FreeBSD has added the same syscall, this only adds the symbol on Linux ports. This syscall is required to provided a fail-safe way to implement the closefrom symbol (BZ #10353). Checked on x86_64-linux-gnu on kernel v5.9 and v5.4. --- NEWS | 3 + include/bits/unistd_ext.h | 6 + manual/llio.texi | 49 +++ sysdeps/unix/sysv/linux/Makefile | 3 +- sysdeps/unix/sysv/linux/Versions | 1 + 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/bits/unistd_ext.h | 22 ++ 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 + sysdeps/unix/sysv/linux/syscalls.list | 1 + sysdeps/unix/sysv/linux/tst-close_range.c | 303 ++++++++++++++++++ .../unix/sysv/linux/x86_64/64/libc.abilist | 1 + .../unix/sysv/linux/x86_64/x32/libc.abilist | 1 + 40 files changed, 419 insertions(+), 1 deletion(-) create mode 100644 include/bits/unistd_ext.h create mode 100644 sysdeps/unix/sysv/linux/tst-close_range.c diff --git a/NEWS b/NEWS index 8e72946c3f..be04b217fe 100644 --- a/NEWS +++ b/NEWS @@ -60,6 +60,9 @@ Major new features: to call async-signal-safe functions (such as raise or execve). This function is currently a GNU extension. +* On Linux, the close_range function has been added. It allows efficiently + closing a range of file descriptors on recent kernels (version 5.9). + Deprecated and removed features, and other changes affecting compatibility: * The function pthread_mutex_consistent_np has been deprecated; programs diff --git a/include/bits/unistd_ext.h b/include/bits/unistd_ext.h new file mode 100644 index 0000000000..277be05746 --- /dev/null +++ b/include/bits/unistd_ext.h @@ -0,0 +1,6 @@ +#include_next + +#ifndef _ISOMAC +extern int __close_range (unsigned int lowfd, unsigned int highfd, int flags); +libc_hidden_proto (__close_range); +#endif diff --git a/manual/llio.texi b/manual/llio.texi index eafc27120d..ea6d34dd5a 100644 --- a/manual/llio.texi +++ b/manual/llio.texi @@ -284,6 +284,55 @@ of trying to close its underlying file descriptor with @code{close}. This flushes any buffered output and updates the stream object to indicate that it is closed. +@deftypefun int close_range (unsigned int @var{lowfd}, unsigned int @var{maxfd}, int @var{flags}) +@standards{Linux, unistd.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}} +@c This is a syscall for Linux v5.9. There is no fallback emulation for +@c older kernels. + +The function @code{close_range} closes the file descriptor from @var{lowfd} +to @var{maxfd} (inclusive). This function is similar to call @code{close} in +specified file descriptor range depending on the @var{flags}. + +This is function is only supported on recent Linux versions and @theglibc{} +does not provide any fallback (the application will need to handle possible +@code{ENOSYS}). + +The @var{flags} add options on how the files are closes. Linux currently +supports: + +@vtable @code +@item CLOSE_RANGE_UNSHARE +Unshare the file descriptor table before closing file descriptors. + +@item CLOSE_RANGE_CLOEXEC +Set the @code{FD_CLOEXEC} bit instead of closing the file descriptor. +@end vtable + +The normal return value from @code{close_range} is @math{0}; a value +of @math{-1} is returned in case of failure. The following @code{errno} error +conditions are defined for this function: + +@table @code +@item EINVAL +The @var{lowfd} value is larger than @var{maxfd} or an unsupported @var{flags} +is used. + +@item ENOMEM +Either there is not enough memory for the operation, or the process is +out of address space. + +@item EMFILE +The process has too many files open. +The maximum number of file descriptors is controlled by the +@code{RLIMIT_NOFILE} resource limit; @pxref{Limits on Resources}. + +@item ENOSYS +The kernel does not implement the required functionality. +@end table +@end deftypefun + + @node I/O Primitives @section Input and Output Primitives diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index faea02bd1b..e308711168 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -116,7 +116,8 @@ tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \ tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux tst-sysvshm-linux \ tst-timerfd tst-ppoll \ tst-clock_adjtime tst-adjtimex tst-ntp_adjtime tst-ntp_gettime \ - tst-ntp_gettimex tst-sigtimedwait tst-misalign-clone + tst-ntp_gettimex tst-sigtimedwait tst-misalign-clone \ + tst-close_range # Test for the symbol version of fcntl that was replaced in glibc 2.28. ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes) diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions index 53cb7b23e2..4884216825 100644 --- a/sysdeps/unix/sysv/linux/Versions +++ b/sysdeps/unix/sysv/linux/Versions @@ -283,6 +283,7 @@ libc { __wait3_time64; __wait4_time64; %endif + close_range; } GLIBC_PRIVATE { # functions used in other libraries diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist index 6730cbdd6b..c32f5898fe 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2409,6 +2409,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 63de4fadc3..cb10eadbb9 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -2508,6 +2508,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 2f13701fd7..a697c930e1 100644 --- a/sysdeps/unix/sysv/linux/arc/libc.abilist +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist @@ -2168,6 +2168,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 9b824f1605..7dbe38dcb7 100644 --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist @@ -302,6 +302,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 443a81b8f7..0ee69506ea 100644 --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist @@ -299,6 +299,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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/bits/unistd_ext.h b/sysdeps/unix/sysv/linux/bits/unistd_ext.h index 2e529be577..bf313e8af8 100644 --- a/sysdeps/unix/sysv/linux/bits/unistd_ext.h +++ b/sysdeps/unix/sysv/linux/bits/unistd_ext.h @@ -33,4 +33,26 @@ not detached and has not been joined. */ extern __pid_t gettid (void) __THROW; +#ifdef __has_include +# if __has_include ("linux/close_range.h") +# include "linux/close_range.h" +# endif #endif +/* Unshare the file descriptor table before closing file descriptors. */ +#ifndef CLOSE_RANGE_UNSHARE +# define CLOSE_RANGE_UNSHARE (1U << 1) +#endif +/* Set the FD_CLOEXEC bit instead of closing the file descriptor. */ +#ifndef CLOSE_RANGE_CLOEXEC +# define CLOSE_RANGE_CLOEXEC (1U << 2) +#endif + +/* Close all file descriptors in the range FD up to MAX_FD. The flag FLAGS + are define by the CLOSE_RANGE prefix. This function behaves like close + on the range, but in a fail-safe where it will either fail and not close + any file descriptor or close all of them. Returns 0 on successor or -1 + for failure (and sets errno accordingly). */ +extern int close_range (unsigned int __fd, unsigned int __max_fd, + int __flags) __THROW; + +#endif /* __USE_GNU */ diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist index 243de3cf93..c5849e1da2 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2434,6 +2434,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 24ae58bb6f..9368379d9d 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2387,6 +2387,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 09bebcd5a1..e4a16d0bcf 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2571,6 +2571,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 0bafe09253..f7a29d00de 100644 --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist @@ -2346,6 +2346,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 c1fcde4c24..7a1b38fe81 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -303,6 +303,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 407651cfd7..64591d99cc 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2514,6 +2514,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 7da722a734..1769dc5c80 100644 --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist @@ -2485,6 +2485,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 c374607b81..4373d181fb 100644 --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist @@ -2482,6 +2482,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 b1f426e053..c714662ff3 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2479,6 +2479,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 066ceb2258..d6d9f3b5f6 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2477,6 +2477,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 51c563ebbe..287fc03201 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2485,6 +2485,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 28db715d8a..92dc711ee2 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2397,6 +2397,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 ab9f2bd42c..b1c4e54a70 100644 --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist @@ -2524,6 +2524,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 83f8513e17..1ed9e1c9a7 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -2541,6 +2541,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 0fad357bf6..953e05cc33 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -2574,6 +2574,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 424ec8d953..e6bcab06d5 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2310,6 +2310,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 9909fd0e9a..525cb85de2 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2605,6 +2605,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 7085989b16..a1d89d2f14 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -2170,6 +2170,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 a855997957..84f7a8561a 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2370,6 +2370,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 12aeb82520..edd1dbbbdb 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -2539,6 +2539,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 e2d746ad5f..19160f33ba 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -2347,6 +2347,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 1ce4b54bf2..8e99b18060 100644 --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist @@ -2394,6 +2394,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 7d01add713..f876e152b7 100644 --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist @@ -2391,6 +2391,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 b5ef3247d7..a6fa1a1b29 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -2534,6 +2534,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 14ae7c8417..4f6166a8f1 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2369,6 +2369,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index 62329abb49..29899eb264 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -99,3 +99,4 @@ pkey_alloc EXTRA pkey_alloc i:ii pkey_alloc pkey_free EXTRA pkey_free i:i pkey_free gettid EXTRA gettid Ei: __gettid gettid tgkill EXTRA tgkill i:iii __tgkill tgkill +close_range EXTRA close_range i:iii __close_range close_range diff --git a/sysdeps/unix/sysv/linux/tst-close_range.c b/sysdeps/unix/sysv/linux/tst-close_range.c new file mode 100644 index 0000000000..dccb6189c5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-close_range.c @@ -0,0 +1,303 @@ +/* Test for the close_range system call. + 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 +#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 void +close_range_test_max_upper_limit (void) +{ + struct support_descriptors *descrs = support_descriptors_list (); + + int lowfd = open_multiple_temp_files (); + + { + int r = close_range (lowfd, ~0U, 0); + if (r == -1 && errno == ENOSYS) + FAIL_UNSUPPORTED ("close_range not supported"); + TEST_COMPARE (r, 0); + } + + support_descriptors_check (descrs); + support_descriptors_free (descrs); +} + +static void +close_range_test_common (int lowfd, unsigned int flags) +{ + const int maximum_fd = lowfd + NFDS; + const int half_fd = lowfd + NFDS / 2; + const int gap_1 = maximum_fd - 8; + + /* Close half of the descriptors and check result. */ + TEST_COMPARE (close_range (lowfd, half_fd, flags), 0); + for (int i = lowfd; i <= half_fd; i++) + { + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } + for (int i = half_fd + 1; i < maximum_fd; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Create some gaps, close up to a threshold, and check result. */ + xclose (lowfd + 57); + xclose (lowfd + 78); + xclose (lowfd + 81); + xclose (lowfd + 82); + xclose (lowfd + 84); + xclose (lowfd + 90); + + TEST_COMPARE (close_range (half_fd + 1, gap_1, flags), 0); + for (int i = half_fd + 1; i < gap_1; i++) + { + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } + for (int i = gap_1 + 1; i < maximum_fd; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Close the remaining but the last one. */ + TEST_COMPARE (close_range (gap_1 + 1, maximum_fd - 1, flags), 0); + for (int i = gap_1 + 1; i < maximum_fd - 1; i++) + { + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } + TEST_VERIFY (fcntl (maximum_fd, F_GETFL) > -1); + + /* Close the last one. */ + TEST_COMPARE (close_range (maximum_fd, maximum_fd, flags), 0); + TEST_COMPARE (fcntl (maximum_fd, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); +} + +/* Basic tests: check if the syscall close ranges with and without gaps. */ +static void +close_range_test (void) +{ + struct support_descriptors *descrs = support_descriptors_list (); + + /* Check if the temporary file descriptor has no no gaps. */ + int lowfd = open_multiple_temp_files (); + + close_range_test_common (lowfd, 0); + + /* Double check by check the /proc. */ + support_descriptors_check (descrs); + support_descriptors_free (descrs); +} + +_Noreturn static int +close_range_test_fn (void *arg) +{ + int lowfd = (int) ((uintptr_t) arg); + close_range_test_common (lowfd, 0); + exit (EXIT_SUCCESS); +} + +/* Check if a clone_range on a subprocess created with CLONE_FILES close + the shared file descriptor table entries in the parent. */ +static void +close_range_test_subprocess (void) +{ + struct support_descriptors *descrs = support_descriptors_list (); + + /* Check if the temporary file descriptor has no no gaps. */ + int lowfd = open_multiple_temp_files (); + + struct support_stack stack = support_stack_alloc (4096); + + pid_t pid = xclone (close_range_test_fn, (void*) (uintptr_t) lowfd, + stack.stack, stack.size, CLONE_FILES | SIGCHLD); + TEST_VERIFY_EXIT (pid > 0); + int status; + xwaitpid (pid, &status, 0); + TEST_VERIFY (WIFEXITED (status)); + TEST_COMPARE (WEXITSTATUS (status), 0); + + support_stack_free (&stack); + + for (int i = lowfd; i < NFDS; i++) + TEST_VERIFY (fcntl (i, F_GETFL) < 0); + + support_descriptors_check (descrs); + support_descriptors_free (descrs); +} + + +_Noreturn static int +close_range_unshare_test_fn (void *arg) +{ + int lowfd = (int) ((uintptr_t) arg); + close_range_test_common (lowfd, CLOSE_RANGE_UNSHARE); + exit (EXIT_SUCCESS); +} + +/* Check if a close_range with CLOSE_RANGE_UNSHARE issued from a subprocess + created with CLONE_FILES does not close the parent file descriptor list. */ +static void +close_range_unshare_test (void) +{ + struct support_descriptors *descrs1 = support_descriptors_list (); + + /* Check if the temporary file descriptor has no no gaps. */ + int lowfd = open_multiple_temp_files (); + + struct support_descriptors *descrs2 = support_descriptors_list (); + + struct support_stack stack = support_stack_alloc (4096); + + pid_t pid = xclone (close_range_unshare_test_fn, (void*) (uintptr_t) lowfd, + stack.stack, stack.size, CLONE_FILES | SIGCHLD); + TEST_VERIFY_EXIT (pid > 0); + int status; + xwaitpid (pid, &status, 0); + TEST_VERIFY (WIFEXITED (status)); + TEST_COMPARE (WEXITSTATUS (status), 0); + + support_stack_free (&stack); + + for (int i = 0; i < NFDS; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + support_descriptors_check (descrs2); + support_descriptors_free (descrs2); + + TEST_COMPARE (close_range (lowfd, lowfd + NFDS, 0), 0); + + support_descriptors_check (descrs1); + support_descriptors_free (descrs1); +} + +static bool +is_in_array (int *arr, size_t len, int fd) +{ + bool r = false; + for (int i = 0; i < len; i++) + if (arr[i] == fd) + return true; + return r; +} + +static void +close_range_cloexec_test (void) +{ + /* Check if the temporary file descriptor has no no gaps. */ + const int lowfd = open_multiple_temp_files (); + + const int maximum_fd = lowfd + NFDS; + const int half_fd = lowfd + NFDS / 2; + const int gap_1 = maximum_fd - 8; + + /* Close half of the descriptors and check result. */ + int r = close_range (lowfd, half_fd, CLOSE_RANGE_CLOEXEC); + if (r == -1 && errno == EINVAL) + { + printf ("%s: CLOSE_RANGE_CLOEXEC not supported\n", __func__); + return; + } + for (int i = lowfd; i <= half_fd; i++) + { + int flags = fcntl (i, F_GETFD); + TEST_VERIFY (flags > -1); + TEST_COMPARE (flags & FD_CLOEXEC, FD_CLOEXEC); + } + for (int i = half_fd + 1; i < maximum_fd; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Create some gaps, close up to a threshold, and check result. */ + static int gap_close[] = { 57, 78, 81, 82, 84, 90 }; + for (int i = 0; i < array_length (gap_close); i++) + xclose (gap_close[i]); + + TEST_COMPARE (close_range (half_fd + 1, gap_1, CLOSE_RANGE_CLOEXEC), 0); + for (int i = half_fd + 1; i < gap_1; i++) + { + int flags = fcntl (i, F_GETFD); + if (is_in_array (gap_close, array_length (gap_close), i)) + TEST_COMPARE (flags, -1); + else + { + TEST_VERIFY (flags > -1); + TEST_COMPARE (flags & FD_CLOEXEC, FD_CLOEXEC); + } + } + for (int i = gap_1 + 1; i < maximum_fd; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Close the remaining but the last one. */ + TEST_COMPARE (close_range (gap_1 + 1, maximum_fd - 1, CLOSE_RANGE_CLOEXEC), + 0); + for (int i = gap_1 + 1; i < maximum_fd - 1; i++) + { + int flags = fcntl (i, F_GETFD); + TEST_VERIFY (flags > -1); + TEST_COMPARE (flags & FD_CLOEXEC, FD_CLOEXEC); + } + TEST_VERIFY (fcntl (maximum_fd, F_GETFL) > -1); + + /* Close the last one. */ + TEST_COMPARE (close_range (maximum_fd, maximum_fd, CLOSE_RANGE_CLOEXEC), 0); + { + int flags = fcntl (maximum_fd, F_GETFD); + TEST_VERIFY (flags > -1); + TEST_COMPARE (flags & FD_CLOEXEC, FD_CLOEXEC); + } +} + +static int +do_test (void) +{ + close_range_test_max_upper_limit (); + close_range_test (); + close_range_test_subprocess (); + close_range_unshare_test (); + close_range_cloexec_test (); + + return 0; +} + +#include diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index 57c4f28d17..e12670c1a4 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2325,6 +2325,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range 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 47211abe4e..9b524d7b72 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2424,6 +2424,7 @@ GLIBC_2.34 aio_suspend64 F GLIBC_2.34 aio_write F GLIBC_2.34 aio_write64 F GLIBC_2.34 call_once F +GLIBC_2.34 close_range F GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_init F