From patchwork Wed Jun 23 18:51:11 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: 43981 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 DA4C3398B437 for ; Wed, 23 Jun 2021 18:52:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DA4C3398B437 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1624474346; bh=wuviU+0J5OLEM3weDlbFv0CTGHKYZxX1oqQF8/SaIXw=; 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=Vy554Y0oMzJi8SsYw4DGTcG907WaTukEcMwiIS7KNlEEPWFO+TKoQveVRF5Q/txnZ CSTMVXkureL3OHiEY64vSxpuL76lNbK3zvxe07wiF6TG4exY2pwc3m8ZMTxmcPlFvQ mA4YGEFKvQnzy1PsQBV/NoVoaRe7+gFeFVUq/tWU= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x832.google.com (mail-qt1-x832.google.com [IPv6:2607:f8b0:4864:20::832]) by sourceware.org (Postfix) with ESMTPS id 8EE2A388A42F for ; Wed, 23 Jun 2021 18:51:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8EE2A388A42F Received: by mail-qt1-x832.google.com with SMTP id e3so2940847qte.0 for ; Wed, 23 Jun 2021 11:51:21 -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=wuviU+0J5OLEM3weDlbFv0CTGHKYZxX1oqQF8/SaIXw=; b=na3z4M388EqS/kx1weYfMkgcDth2YPU3IaIiGRnNS7VsfnJ9iblJBK9ddb21LG7VQ+ BOpd9ppTjbGpGa8KLDY+JBTkeQXES90heMbI3XWTYNrxd4zeJLqzG7e7uwLP43/yOwOV b92Hm/6sEvRwIf4Ew+Nuig58qBWCPPihQpBHGzsukkVQRKlmcO2DK4KzzzKYlAaF1/yZ AsJmFGlptHQYJs8fPJGAAzgjADnu1LYK2tYUl1aG5/oghdYS95DxqxQ4cEvfDZPp/6st qJp3PvvgiE7J6l9d5VVUo/0wjXYm9zByiH5NEWps72mt9wZPD71kUnl0qd/kHUENPFNR d9ug== X-Gm-Message-State: AOAM5323FL1GQboEFe6S8otkYF8bKU1d0iNjQV0hajFzjL60k+lPFlSV Xj+3qsoJlR9XlIjZ3V6SBTqp6L3phQKvjg== X-Google-Smtp-Source: ABdhPJwBX/wDR2kNrKhp3RHTWrWCqCjlzfv61e/FEUNKu8guWVx84vLLvtRMO7lnwFP/2jbfFvRBBg== X-Received: by 2002:ac8:5f0d:: with SMTP id x13mr1295368qta.69.1624474280995; Wed, 23 Jun 2021 11:51:20 -0700 (PDT) Received: from birita.. ([177.194.59.218]) by smtp.gmail.com with ESMTPSA id c11sm492293qth.29.2021.06.23.11.51.20 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Jun 2021 11:51:20 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 1/5] support: Add support_stack_alloc Date: Wed, 23 Jun 2021 15:51:11 -0300 Message-Id: <20210623185115.395812-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210623185115.395812-1-adhemerval.zanella@linaro.org> References: <20210623185115.395812-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.4 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 Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The code to allocate a stack from xsigstack is refactored so it can be more generic. --- support/Makefile | 1 + support/support.h | 19 +++++++++ support/support_stack_alloc.c | 76 +++++++++++++++++++++++++++++++++++ support/xsigstack.c | 43 +++----------------- 4 files changed, 101 insertions(+), 38 deletions(-) create mode 100644 support/support_stack_alloc.c diff --git a/support/Makefile b/support/Makefile index 278f4627d8..f5410545a1 100644 --- a/support/Makefile +++ b/support/Makefile @@ -39,6 +39,7 @@ libsupport-routines = \ resolv_response_context_free \ resolv_test \ set_fortify_handler \ + support_stack_alloc \ support-xfstat \ support-xfstat-time64 \ support-xstat \ diff --git a/support/support.h b/support/support.h index 9ec8ecb8d7..dbd270c78d 100644 --- a/support/support.h +++ b/support/support.h @@ -164,6 +164,25 @@ timer_t support_create_timer (uint64_t sec, long int nsec, bool repeat, /* Disable the timer TIMER. */ void support_delete_timer (timer_t timer); +struct support_stack +{ + void *stack; + size_t size; + size_t guardsize; +}; + +/* Allocate stack suitable to used with xclone or sigaltstack call. The stack + will have a minimum size of SIZE + MINSIGSTKSZ bytes, rounded up to a whole + number of pages. There will be a large (at least 1 MiB) inaccessible guard + bands on either side of it. + The returned value on ALLOC_BASE and ALLOC_SIZE will be the usable stack + region, excluding the GUARD_SIZE allocated area. + It also terminates the process on error. */ +struct support_stack support_stack_alloc (size_t size); + +/* Deallocate the STACK. */ +void support_stack_free (struct support_stack *stack); + __END_DECLS #endif /* SUPPORT_H */ diff --git a/support/support_stack_alloc.c b/support/support_stack_alloc.c new file mode 100644 index 0000000000..08323f43d5 --- /dev/null +++ b/support/support_stack_alloc.c @@ -0,0 +1,76 @@ +/* Allocate a stack suitable to be used with xclone or xsigaltstack. + 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 /* roundup, MAX */ + +#ifndef MAP_NORESERVE +# define MAP_NORESERVE 0 +#endif +#ifndef MAP_STACK +# define MAP_STACK 0 +#endif + +struct support_stack +support_stack_alloc (size_t size) +{ + size_t pagesize = sysconf (_SC_PAGESIZE); + if (pagesize == -1) + FAIL_EXIT1 ("sysconf (_SC_PAGESIZE): %m\n"); + + /* Always supply at least MINSIGSTKSZ space; passing 0 as size means + only that much space. No matter what the number is, round it up + to a whole number of pages. */ + size_t stacksize = roundup (size + MINSIGSTKSZ, pagesize); + + /* The guard bands need to be large enough to intercept offset + accesses from a stack address that might otherwise hit another + mapping. Make them at least twice as big as the stack itself, to + defend against an offset by the entire size of a large + stack-allocated array. The minimum is 1MiB, which is arbitrarily + chosen to be larger than any "typical" wild pointer offset. + Again, no matter what the number is, round it up to a whole + number of pages. */ + size_t guardsize = roundup (MAX (2 * stacksize, 1024 * 1024), pagesize); + size_t alloc_size = guardsize + stacksize + guardsize; + /* Use MAP_NORESERVE so that RAM will not be wasted on the guard + bands; touch all the pages of the actual stack before returning, + so we know they are allocated. */ + void *alloc_base = xmmap (0, + alloc_size, + PROT_NONE, + MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE|MAP_STACK, + -1); + xmprotect (alloc_base + guardsize, stacksize, PROT_READ | PROT_WRITE); + memset (alloc_base + guardsize, 0xA5, stacksize); + return (struct support_stack) { alloc_base + guardsize, + stacksize, guardsize }; +} + +void +support_stack_free (struct support_stack *stack) +{ + void *alloc_base = (void *)((uintptr_t) stack->stack - stack->guardsize); + size_t alloc_size = stack->size + 2 * stack->guardsize; + xmunmap (alloc_base, alloc_size); +} diff --git a/support/xsigstack.c b/support/xsigstack.c index a2f0e3269a..a471c853cb 100644 --- a/support/xsigstack.c +++ b/support/xsigstack.c @@ -37,8 +37,7 @@ structures. */ struct sigstack_desc { - void *alloc_base; /* Base address of the complete allocation. */ - size_t alloc_size; /* Size of the complete allocation. */ + struct support_stack stack; stack_t alt_stack; /* The address and size of the stack itself. */ stack_t old_stack; /* The previous signal stack. */ }; @@ -46,43 +45,11 @@ struct sigstack_desc void * xalloc_sigstack (size_t size) { - size_t pagesize = sysconf (_SC_PAGESIZE); - if (pagesize == -1) - FAIL_EXIT1 ("sysconf (_SC_PAGESIZE): %m\n"); - - /* Always supply at least MINSIGSTKSZ space; passing 0 as size means - only that much space. No matter what the number is, round it up - to a whole number of pages. */ - size_t stacksize = roundup (size + MINSIGSTKSZ, pagesize); - - /* The guard bands need to be large enough to intercept offset - accesses from a stack address that might otherwise hit another - mapping. Make them at least twice as big as the stack itself, to - defend against an offset by the entire size of a large - stack-allocated array. The minimum is 1MiB, which is arbitrarily - chosen to be larger than any "typical" wild pointer offset. - Again, no matter what the number is, round it up to a whole - number of pages. */ - size_t guardsize = roundup (MAX (2 * stacksize, 1024 * 1024), pagesize); - struct sigstack_desc *desc = xmalloc (sizeof (struct sigstack_desc)); - desc->alloc_size = guardsize + stacksize + guardsize; - /* Use MAP_NORESERVE so that RAM will not be wasted on the guard - bands; touch all the pages of the actual stack before returning, - so we know they are allocated. */ - desc->alloc_base = xmmap (0, - desc->alloc_size, - PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE|MAP_STACK, - -1); - - xmprotect (desc->alloc_base, guardsize, PROT_NONE); - xmprotect (desc->alloc_base + guardsize + stacksize, guardsize, PROT_NONE); - memset (desc->alloc_base + guardsize, 0xA5, stacksize); - - desc->alt_stack.ss_sp = desc->alloc_base + guardsize; + desc->stack = support_stack_alloc (size); + desc->alt_stack.ss_sp = desc->stack.stack; desc->alt_stack.ss_flags = 0; - desc->alt_stack.ss_size = stacksize; + desc->alt_stack.ss_size = desc->stack.size; if (sigaltstack (&desc->alt_stack, &desc->old_stack)) FAIL_EXIT1 ("sigaltstack (new stack: sp=%p, size=%zu, flags=%u): %m\n", @@ -101,7 +68,7 @@ xfree_sigstack (void *stack) FAIL_EXIT1 ("sigaltstack (restore old stack: sp=%p, size=%zu, flags=%u): " "%m\n", desc->old_stack.ss_sp, desc->old_stack.ss_size, desc->old_stack.ss_flags); - xmunmap (desc->alloc_base, desc->alloc_size); + support_stack_free (&desc->stack); free (desc); } From patchwork Wed Jun 23 18:51:12 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: 43982 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 51B3F398B85C for ; Wed, 23 Jun 2021 18:53:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 51B3F398B85C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1624474391; bh=WM6JMiGYKqiDnRhU+eSyqP7igawh7WkpXSl3LCxAbqs=; 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=x1S9aS20Vps7ynOyt+eOYt6huFoXL/TNNwZSuK08DBpJbL93AwYRy5Vug0E6gIML9 hYkUZdlEyoUhSi7cHNWmSACjuKyynM908Eac96LcqgOq/tqgV5EbOT8WLjH0qwSbwS E3PbhTikktdbAAzvcW6jVJ0NTyTXLsgWXS/jtY4I= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x831.google.com (mail-qt1-x831.google.com [IPv6:2607:f8b0:4864:20::831]) by sourceware.org (Postfix) with ESMTPS id B597F383803E for ; Wed, 23 Jun 2021 18:51:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B597F383803E Received: by mail-qt1-x831.google.com with SMTP id w26so2865733qto.13 for ; Wed, 23 Jun 2021 11:51:22 -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=WM6JMiGYKqiDnRhU+eSyqP7igawh7WkpXSl3LCxAbqs=; b=aFwSbgOngCyxStmuuyyWtuZ1mbbRyk24VVykDQozW1+AcJ3wnNn31r940RKYSMQM8m 4TU4p3YXm3SxlHjtIT3S02r3HurpJKmAqCZ9ck4NULVXXq2vOqyG7+T7pzth+dgUCVmJ MyoHhqb4owaUIgG9CK9fa5lD5xFfCUDUXnfrRRjahMB8dTNs7sthBuE9IVCMr3XxCrwi xP1LoYDq0u+ItK50Dh5Fqy+p4JJ1NYknvqKJBbd2goUInAA+JZk1PPsZ8lT0eAG3LRLc MPneG+Ptupg+Gg/Fsa3rn5+SmdknPKUb8im030dnmxv1nu9PSDWbSMihUNsfBeM+pNlo tjxA== X-Gm-Message-State: AOAM533lIGST8nCXZmimK9J0NvcWgE4vriNNQtiITSNxkZPb8dcmUmTa Oea7HVqyn3iJ6uGbVeJGSWZ0Ix60pMkscA== X-Google-Smtp-Source: ABdhPJzveAuCnVULn6dbuAb41JBf8JNBzSejD7wru7W6JXn2i3pCODwC0HU60yzCVN4tfyNyFMg8mA== X-Received: by 2002:ac8:5bc8:: with SMTP id b8mr1282282qtb.386.1624474282168; Wed, 23 Jun 2021 11:51:22 -0700 (PDT) Received: from birita.. ([177.194.59.218]) by smtp.gmail.com with ESMTPSA id c11sm492293qth.29.2021.06.23.11.51.21 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Jun 2021 11:51:21 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 2/5] support: Add xclone Date: Wed, 23 Jun 2021 15:51:12 -0300 Message-Id: <20210623185115.395812-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210623185115.395812-1-adhemerval.zanella@linaro.org> References: <20210623185115.395812-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.4 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 Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" It is a wrapper for Linux clone syscall, to simplify the call to the use only the most common arguments and remove architecture specific handling (such as ia64 different name and signature). --- support/Makefile | 1 + support/xclone.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ support/xsched.h | 34 ++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 support/xclone.c create mode 100644 support/xsched.h diff --git a/support/Makefile b/support/Makefile index f5410545a1..a462781718 100644 --- a/support/Makefile +++ b/support/Makefile @@ -104,6 +104,7 @@ libsupport-routines = \ xclock_gettime_time64 \ xclock_settime \ xclock_settime_time64 \ + xclone \ xclose \ xchmod \ xconnect \ diff --git a/support/xclone.c b/support/xclone.c new file mode 100644 index 0000000000..924d2b8754 --- /dev/null +++ b/support/xclone.c @@ -0,0 +1,50 @@ +/* Auxiliary functions to issue the clone syscall. + 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 + . */ + +#ifdef __linux__ +# include +# include /* For _STACK_GROWS_{UP,DOWN}. */ +# include + +pid_t +xclone (int (*fn) (void *arg), void *arg, void *stack, size_t stack_size, + int flags) +{ + pid_t r = -1; + +# ifdef __ia64__ + extern int __clone2 (int (*fn) (void *arg), void *stack, size_t stack_size, + int flags, void *arg, ...); + r = __clone2 (f, stack, stack_size, flags, arg, /* ptid */ NULL, + /* tls */ NULL, /* ctid */ ctid); +# else +# if _STACK_GROWS_DOWN + r = clone (fn, stack + stack_size, flags, arg, /* ptid */ NULL, + /* tls */ NULL, /* ctid */ NULL); +# elif _STACK_GROWS_UP + r = clone (fn, stack, flags, arg, /* ptid */ NULL, /* tls */ NULL, + &ctid); +# endif +# endif + + if (r < 0) + FAIL_EXIT1 ("clone: %m"); + + return r; +} +#endif diff --git a/support/xsched.h b/support/xsched.h new file mode 100644 index 0000000000..eefd731940 --- /dev/null +++ b/support/xsched.h @@ -0,0 +1,34 @@ +/* Wrapper for sched.h functions. + 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 + . */ + +#ifndef SUPPORT_XSCHED_H +#define SUPPORT_XSCHED_H + +__BEGIN_DECLS + +#include +#include + +#ifdef __linux__ +pid_t xclone (int (*fn) (void *arg), void *arg, void *stack, + size_t stack_size, int flags); +#endif + +__END_DECLS + +#endif From patchwork Wed Jun 23 18:51:13 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: 43983 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 B8F8D398B43A for ; Wed, 23 Jun 2021 18:53:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B8F8D398B43A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1624474435; bh=8mrE4ZY0kxnx584SbUGsg3lruLwh46I74nD7CHaRDuI=; 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=KfrwxL00fDbRTzmQEGfFzQF7blZ8/hDno94oWdKEnNKCvQpiwxCvW85+5PaIvJXhT H3Ms2essL3P+AWPEpAumj+dcqm14VIh7zEkM8g/qXjtCrMZmscru2fOuM8zQn1HIx7 Em37cqdUnhj/76Y9YLNpcKlWbuYJXYir2BhsuL0c= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x72b.google.com (mail-qk1-x72b.google.com [IPv6:2607:f8b0:4864:20::72b]) by sourceware.org (Postfix) with ESMTPS id 75946393F827 for ; Wed, 23 Jun 2021 18:51:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 75946393F827 Received: by mail-qk1-x72b.google.com with SMTP id bl4so7812366qkb.8 for ; Wed, 23 Jun 2021 11:51:24 -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=8mrE4ZY0kxnx584SbUGsg3lruLwh46I74nD7CHaRDuI=; b=HdWk5jOfaVcy7hRqCcoeyRz3xFDxh2/E4kGS3eCu6bY5JwaMA65KD2Tl4WFNW+ZmpN pKMGttzkwgylyzQ1s5Zke8LLUacNPWd+xrLvkymYeQAZ1zoVExu1HqDh/xwNqgiyhvBx aoZcKq+cbEekKd4+W8OKWtWf51jQA9ACRaEqYOieVDPeOQksOgRY75Dw+nPZ0vDisd8n bw25tP+XcaSeqUUiRE5f+T3lO1CmRNxK44TvBeiFvyIWyEscdWOEJaGrww5qAG7b/prt GmO0GGWyIbbaDfv7LMjzq9D5s1FZbdPzAfBBwpb/bvP9HyqhzvNgS0vwGnPtE9RJQnP+ AElg== X-Gm-Message-State: AOAM530zDhILe1+Kd1zzMTjmf9DIiQVAJZG2gLn8h2lOSD30yN9GyQuQ Su7IUVptu8ziT6oEDjDCe/49jTz8ruP7Kw== X-Google-Smtp-Source: ABdhPJwj14Fn1aqiEeohP85cV5fKr/wLo2147Bo0k6wf9YSTpYhYLDIlKcyDjHa7wWC+NZBfANwZmA== X-Received: by 2002:a05:620a:307:: with SMTP id s7mr1456513qkm.213.1624474283479; Wed, 23 Jun 2021 11:51:23 -0700 (PDT) Received: from birita.. ([177.194.59.218]) by smtp.gmail.com with ESMTPSA id c11sm492293qth.29.2021.06.23.11.51.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Jun 2021 11:51:23 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 3/5] linux: Add close_range Date: Wed, 23 Jun 2021 15:51:13 -0300 Message-Id: <20210623185115.395812-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210623185115.395812-1-adhemerval.zanella@linaro.org> References: <20210623185115.395812-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.4 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 Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" 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 | 45 +++ 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, 415 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 48d77d706f..a654694e01 100644 --- a/NEWS +++ b/NEWS @@ -47,6 +47,9 @@ Major new features: with names ending with .conf to logically classify the converter modules in that directory. +* 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 cbc4909fd5..3613ead72c 100644 --- a/manual/llio.texi +++ b/manual/llio.texi @@ -284,6 +284,51 @@ 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 +@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 88d7cd7c1b..35a90fd082 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 ea0b22d7af..c16c8f5acb 100644 --- a/sysdeps/unix/sysv/linux/Versions +++ b/sysdeps/unix/sysv/linux/Versions @@ -270,6 +270,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 42e240e284..b4fe47f106 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2349,6 +2349,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 fad54555dc..7f2efdb4b2 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -2442,6 +2442,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 907716ec39..1dc13bbc63 100644 --- a/sysdeps/unix/sysv/linux/arc/libc.abilist +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist @@ -2108,6 +2108,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 50f987a429..7ed5f95b0a 100644 --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist @@ -279,6 +279,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 bf9038af84..3b2e38f2d5 100644 --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist @@ -276,6 +276,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 afb91f6f43..c67320e0a3 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2368,6 +2368,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 125f8a269a..4d49b632b3 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2322,6 +2322,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 517753bdd1..7fdd181a8d 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2506,6 +2506,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 23d0928360..f719aa9ee4 100644 --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist @@ -2282,6 +2282,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 dd5fb50b18..3616c567e3 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -280,6 +280,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 cb1d553361..4180cdf07d 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2449,6 +2449,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 6a20a6fdf2..82f5959756 100644 --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist @@ -2419,6 +2419,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 4c21cbb64d..53fb9ffaf8 100644 --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist @@ -2416,6 +2416,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 f83ba2f780..76f8f675ea 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2414,6 +2414,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 347bbddb94..9d294bfcf9 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2412,6 +2412,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 26b7ab529b..44fb849bc9 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2420,6 +2420,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 e667b0e553..102ec2a2f9 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2338,6 +2338,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 89a1cc7da6..c5c6844a01 100644 --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist @@ -2458,6 +2458,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 f364c5219e..8111a6d886 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -2476,6 +2476,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 f5bcc78afe..f65efa3c54 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -2509,6 +2509,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 6032716053..7cce3dca8c 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2246,6 +2246,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 8c5494e1dc..65ccafb1d9 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2545,6 +2545,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 d7db279c1e..a34c8c30fc 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -2110,6 +2110,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 ef03dc0f9e..85a5815d7b 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2310,6 +2310,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 9118cb68ec..b63b3a5f0e 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -2474,6 +2474,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 66c01bd7e7..b874e3d48f 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -2283,6 +2283,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 c40eb412c2..4eabae900d 100644 --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist @@ -2329,6 +2329,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 1412d33835..ad302d997f 100644 --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist @@ -2326,6 +2326,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 7b55d34753..7c3f29d8b4 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -2467,6 +2467,7 @@ GLIBC_2.34 __wait4_time64 F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 cfd5f38864..d1442eac11 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2303,6 +2303,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 01ec2bfa95..53575669c7 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -101,3 +101,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..86c9f08845 --- /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 17be05f14f..06274a69e8 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2261,6 +2261,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 a9db18906b..98e05351a8 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2364,6 +2364,7 @@ GLIBC_2.34 __pthread_unwind_next F GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 From patchwork Wed Jun 23 18:51:14 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: 43984 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 4B190398B86E for ; Wed, 23 Jun 2021 18:54:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4B190398B86E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1624474487; bh=0ftE/fWX+4TA0NzgeQ2NaDGYrF3hF2/lcOlIPcIXxuw=; 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=QaeaO7D4VZqCbcdp4obuWzyBnqpWumvOIkh5YTmGZ8UU6TJDQGRomg0qqkjHi6YnJ aanMriPEntFfATbmZaI8ZuACKVSH4M5pZMyCn5rdhvuErmqUWW5hx3PmBy9ZbeS/jr RgmaLN1my8xVLZGlZV91hyJBlwOdjdgMi2LN1cd4= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x834.google.com (mail-qt1-x834.google.com [IPv6:2607:f8b0:4864:20::834]) by sourceware.org (Postfix) with ESMTPS id B1521398B848 for ; Wed, 23 Jun 2021 18:51:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B1521398B848 Received: by mail-qt1-x834.google.com with SMTP id d9so2887828qtx.8 for ; Wed, 23 Jun 2021 11:51:25 -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=0ftE/fWX+4TA0NzgeQ2NaDGYrF3hF2/lcOlIPcIXxuw=; b=YCpXtoG5G57JBRIoE/N9Ic4YKlKk0PEXk/1f0lDcFPRqgJ+PwM3IcEMPNG+HE9c2N4 V6GB9XoJVOoem6z2+WrKL2fjXpTFeT4Gdfu24EV154ykD5TGMyukqMsWwdSVJ8o99HUs itQGjabflCRCNkgOLjHBsiO3oZHfbfeKORAbzTrtKJvmnNC7fipLz9XiylFM8JhV3GoD iE5yM1CjWaf2yTFHabzS7Qg8uXhs1obJ4AJpUnPA418v5UcawaZourO4qf7vWrr2a7Hn M1XA6DeiX1Mh8HuQ/1kcrknLBfrduDfQZIE5t00OAaEqw2NU79j/YDMbCm1Nx65ZTYrD TEog== X-Gm-Message-State: AOAM533ynHl366OerNES2O1WI59dZIzdxdZ9AIjvq4b4GoeauDwvWPqw rrSkFDQhZOWl06Np9eg05HlUsEuULKB+cA== X-Google-Smtp-Source: ABdhPJwrlwP+mfSyORGnnH7uS3ct+jGb11YrPU/opYNT6HiOOl+20tclIebYeGtxemjTKv+Y+BuEzA== X-Received: by 2002:a05:622a:5ca:: with SMTP id d10mr1265479qtb.273.1624474284766; Wed, 23 Jun 2021 11:51:24 -0700 (PDT) Received: from birita.. ([177.194.59.218]) by smtp.gmail.com with ESMTPSA id c11sm492293qth.29.2021.06.23.11.51.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Jun 2021 11:51:24 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 4/5] io: Add closefrom [BZ #10353] Date: Wed, 23 Jun 2021 15:51:14 -0300 Message-Id: <20210623185115.395812-5-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210623185115.395812-1-adhemerval.zanella@linaro.org> References: <20210623185115.395812-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.4 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 Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" 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. Although it was raised the questioning whether getdents on /proc/self/fd might return disjointed entries when file descriptor are closed; it does not seems the case on my testing on multiple kernel (v4.18, v5.4, v5.9) and the same strategy is used on different projects [1][2][3][5]. 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 a654694e01..031898d425 100644 --- a/NEWS +++ b/NEWS @@ -50,6 +50,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 34872d8b41..12044a8531 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -156,6 +156,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 1a16990205..ebb7d56d67 100644 --- a/io/Makefile +++ b/io/Makefile @@ -56,7 +56,8 @@ routines := \ sendfile sendfile64 copy_file_range \ utimensat futimens file_change_detection \ fts64-time64 \ - ftw64-time64 + ftw64-time64 \ + closefrom others := pwd test-srcs := ftwtest ftwtest-time64 @@ -77,6 +78,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ tst-lutimes \ tst-futimens \ tst-utimensat \ + tst-closefrom \ tests-time64 := \ tst-futimens-time64 \ diff --git a/io/Versions b/io/Versions index 88caf76bbc..4e19540885 100644 --- a/io/Versions +++ b/io/Versions @@ -137,6 +137,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 c3232ba32e..76d9e150f2 100644 --- a/sysdeps/mach/hurd/i386/libc.abilist +++ b/sysdeps/mach/hurd/i386/libc.abilist @@ -2218,6 +2218,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 dladdr F GLIBC_2.34 dladdr1 F GLIBC_2.34 dlclose F diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 35a90fd082..2f83da187f 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 \ pselect32 \ xstat fxstat lxstat xstat64 fxstat64 lxstat64 \ fxstatat fxstatat64 \ - xmknod xmknodat convert_scm_timestamps + xmknod xmknodat convert_scm_timestamps \ + 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 b4fe47f106..e5ec01277d 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2350,6 +2350,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 7f2efdb4b2..19f7a7fca4 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -2443,6 +2443,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 1dc13bbc63..ce6c13989a 100644 --- a/sysdeps/unix/sysv/linux/arc/libc.abilist +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist @@ -2109,6 +2109,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 7ed5f95b0a..57e8456a3c 100644 --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist @@ -280,6 +280,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 3b2e38f2d5..de42eccbba 100644 --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist @@ -277,6 +277,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 c67320e0a3..f95d5ebbeb 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2369,6 +2369,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 4d49b632b3..a9d7fb1a93 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2323,6 +2323,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 7fdd181a8d..1deab899b1 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2507,6 +2507,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 f719aa9ee4..13121df7e0 100644 --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist @@ -2283,6 +2283,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 3616c567e3..e4fb78bf8e 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -281,6 +281,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 4180cdf07d..b21d6b04af 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2450,6 +2450,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 82f5959756..7386b5360c 100644 --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist @@ -2420,6 +2420,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 53fb9ffaf8..c4c3f18e4d 100644 --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist @@ -2417,6 +2417,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 76f8f675ea..b500aa4db3 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2415,6 +2415,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 9d294bfcf9..8260c3ba4f 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2413,6 +2413,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 44fb849bc9..b58b8eef2d 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2421,6 +2421,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 102ec2a2f9..3f19142fee 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2339,6 +2339,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 c5c6844a01..a1d7b0c25f 100644 --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist @@ -2459,6 +2459,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 8111a6d886..1f81867311 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -2477,6 +2477,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 f65efa3c54..9f74a84ead 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -2510,6 +2510,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 7cce3dca8c..8add515ff4 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2247,6 +2247,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 65ccafb1d9..ab7489200b 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2546,6 +2546,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 a34c8c30fc..273c579b2d 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -2111,6 +2111,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 85a5815d7b..9ae1c2ea89 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2311,6 +2311,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 b63b3a5f0e..622d19d754 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -2475,6 +2475,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 b874e3d48f..464e4cefde 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -2284,6 +2284,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 4eabae900d..d75a0ec228 100644 --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist @@ -2330,6 +2330,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 ad302d997f..0eaeffda80 100644 --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist @@ -2327,6 +2327,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 7c3f29d8b4..79e3d5a658 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -2468,6 +2468,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 d1442eac11..727b767863 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2304,6 +2304,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 06274a69e8..fc84da9bae 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2262,6 +2262,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 98e05351a8..2c44f71119 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2365,6 +2365,7 @@ GLIBC_2.34 _pthread_cleanup_pop F GLIBC_2.34 _pthread_cleanup_push 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 From patchwork Wed Jun 23 18:51:15 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: 43985 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 4804A3889819 for ; Wed, 23 Jun 2021 18:55:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4804A3889819 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1624474538; bh=FOJY+bwWAxIQ8YW3YVFN5t5gW+PZCFyYRBI4GbaRqpg=; 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=oC1XgNyjvWv/zpa9dZXuOxHrq/kl5QQTXGcRQUC3jMGjHVqWn63eiB3tVsLSmWwW9 PyDN/TirNnszF8Om3pwMpbG1/rQvdTD56lAY0CMfUMz6KLOJTb+28bTKWS17b3xLh1 LcyxFrdY9ByFzq7h0yHgixwuJQ7g+5En/LSrVq1c= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x72f.google.com (mail-qk1-x72f.google.com [IPv6:2607:f8b0:4864:20::72f]) by sourceware.org (Postfix) with ESMTPS id 266D5398B437 for ; Wed, 23 Jun 2021 18:51:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 266D5398B437 Received: by mail-qk1-x72f.google.com with SMTP id j184so7841766qkd.6 for ; Wed, 23 Jun 2021 11:51:27 -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=FOJY+bwWAxIQ8YW3YVFN5t5gW+PZCFyYRBI4GbaRqpg=; b=uPCKG1UP7lj6MhGxSjzsaqpnjxo1H5dYpegMqKxF0RE0WvkyI8/X8DbKWIyUNOgAxG axPXY2ck498koWRxUtc0OUVI33zcPX+IbJmOsDIaKHGnH4LU4E4iMVo6tMYOn3E2vV2d /WtAY21niE1Wvch+Pvb9QdmJ0mZEsNtk9P/6Nf+w+DJ7PXch3p4EJ2zD7WoxxtWZxsME 92LVUrNfmU3Atg2YauQEC8ypXMgPgOg6Z0IzPQK2GTuJi2lYC91B48t5u0sAipdHgOQr O0j6mnKrnBB5GLCZcKXOAZsSrThkPDRYsEK4nSKJiZfHYbPkXFOL4wCrBH06Akmr70G0 uf4w== X-Gm-Message-State: AOAM531ZgWlAeCBN4lmAMBlNK/O5OtIn2JS+HtBAvrX3V9vFnAMtDn4q lrc8pILh0Pk5sS3dadOCaOC+td/x9NGyDg== X-Google-Smtp-Source: ABdhPJx/nBAPlmfH8s9/pmRBrwsyuyLYhFsXMvb741a9LXJEejYzcUhpxJ2ixOoFGUrsJRkNE8+iWQ== X-Received: by 2002:a37:8c47:: with SMTP id o68mr1482545qkd.482.1624474286200; Wed, 23 Jun 2021 11:51:26 -0700 (PDT) Received: from birita.. ([177.194.59.218]) by smtp.gmail.com with ESMTPSA id c11sm492293qth.29.2021.06.23.11.51.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Jun 2021 11:51:25 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 5/5] posix: Add posix_spawn_file_actions_closefrom_np Date: Wed, 23 Jun 2021 15:51:15 -0300 Message-Id: <20210623185115.395812-6-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210623185115.395812-1-adhemerval.zanella@linaro.org> References: <20210623185115.395812-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.4 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 Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" This patch adds a way to close a range of file descriptors on posix_spawn as a new file action. The API is similar to the one provided by Solaris 11 [1], where the file action causes the all open file descriptors greater than or equal to input on to be closed when the new process is spawned. The function posix_spawn_file_actions_closefrom_np is safe to be implemented by iterating over /proc/self/fd, since the Linux spawni.c helper process does not use CLONE_FILES, so its has own file descriptor table and any failure (in /proc operation) aborts the process creation and returns an error to the caller. I am aware that this file action might be redundant to the current approach of POSIX in promoting O_CLOEXEC in more interfaces. However O_CLOEXEC is still not the default and for some specific usages, the caller needs to close all possible file descriptors to avoid them leaking. Some examples are CPython (discussed in BZ#10353) and OpenJDK jspawnhelper [2] (where OpenJDK spawns a helper process to exactly closes all file descriptors). Most likely any environment which calls functions that might open file descriptor under the hood and aim to use posix_spawn might face the same requirement. Checked on x86_64-linux-gnu, i686-linux-gnu, powerpc64le-linux-gnu, and aarch64-linux-gnu. [1] https://docs.oracle.com/cd/E36784_01/html/E36874/posix-spawn-file-actions-addclosefrom-np-3c.html [2] https://github.com/openjdk/jdk/blob/master/src/java.base/unix/native/libjava/childproc.c#L82 --- NEWS | 5 + include/unistd.h | 2 +- posix/Makefile | 4 +- posix/Versions | 1 + posix/spawn.h | 8 + posix/spawn_faction_addclosefrom.c | 57 ++++ posix/spawn_faction_destroy.c | 1 + posix/spawn_int.h | 6 + posix/tst-spawn5.c | 284 ++++++++++++++++++ sysdeps/generic/spawn_int_def.h | 24 ++ sysdeps/mach/hurd/i386/libc.abilist | 1 + sysdeps/mach/hurd/spawni.c | 4 + sysdeps/posix/spawni.c | 4 + 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 | 3 +- sysdeps/unix/sysv/linux/closefrom_fallback.c | 8 +- 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/spawn_int_def.h | 25 ++ sysdeps/unix/sysv/linux/spawni.c | 34 ++- .../unix/sysv/linux/x86_64/64/libc.abilist | 1 + .../unix/sysv/linux/x86_64/x32/libc.abilist | 1 + 49 files changed, 482 insertions(+), 21 deletions(-) create mode 100644 posix/spawn_faction_addclosefrom.c create mode 100644 posix/tst-spawn5.c create mode 100644 sysdeps/generic/spawn_int_def.h create mode 100644 sysdeps/unix/sysv/linux/spawn_int_def.h diff --git a/NEWS b/NEWS index 031898d425..47fe062ed0 100644 --- a/NEWS +++ b/NEWS @@ -54,6 +54,11 @@ Major new features: greater than given integer. This function is a GNU extension, although it also present in other systems. +* The posix_spawn_file_actions_closefrom_np function has been added, enabling + posix_spawn and posix_spawnp to close all file descriptors great than or + equal to a giver integer. This function is a GNU extension, although + Solaris also provides a similar function. + 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 12044a8531..8bcf164f46 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -156,7 +156,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 _Bool __closefrom_fallback (int __lowfd, _Bool) 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/posix/Makefile b/posix/Makefile index 8d139e54f6..50d17d19de 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -57,6 +57,7 @@ routines := \ spawn_faction_init spawn_faction_destroy spawn_faction_addclose \ spawn_faction_addopen spawn_faction_adddup2 spawn_valid_fd \ spawn_faction_addchdir spawn_faction_addfchdir \ + spawn_faction_addclosefrom \ spawnattr_init spawnattr_destroy \ spawnattr_getdefault spawnattr_setdefault \ spawnattr_getflags spawnattr_setflags \ @@ -106,7 +107,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \ tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \ tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \ bug-regex38 tst-regcomp-truncated tst-spawn-chdir \ - tst-wordexp-nocmd tst-execveat + tst-wordexp-nocmd tst-execveat tst-spawn5 # Test for the glob symbol version that was replaced in glibc 2.27. ifeq ($(have-GLIBC_2.26)$(build-shared),yesyes) @@ -275,6 +276,7 @@ tst-exec-static-ARGS = $(tst-exec-ARGS) tst-execvpe5-ARGS = -- $(host-test-program-cmd) tst-spawn-ARGS = -- $(host-test-program-cmd) tst-spawn-static-ARGS = $(tst-spawn-ARGS) +tst-spawn5-ARGS = -- $(host-test-program-cmd) tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir); pwd` $(objpfx)tst-dir tst-chmod-ARGS = $(objdir) tst-vfork3-ARGS = --test-dir=$(objpfx) diff --git a/posix/Versions b/posix/Versions index 5983144d01..f36756b832 100644 --- a/posix/Versions +++ b/posix/Versions @@ -153,6 +153,7 @@ libc { } GLIBC_2.34 { execveat; + posix_spawn_file_actions_addclosefrom_np; } GLIBC_PRIVATE { __libc_fork; __libc_pread; __libc_pwrite; diff --git a/posix/spawn.h b/posix/spawn.h index a29da028cc..990d8a6ba2 100644 --- a/posix/spawn.h +++ b/posix/spawn.h @@ -213,6 +213,14 @@ extern int posix_spawn_file_actions_addchdir_np (posix_spawn_file_actions_t * extern int posix_spawn_file_actions_addfchdir_np (posix_spawn_file_actions_t *, int __fd) __THROW __nonnull ((1)); + +/* Add an action to close all file descriptor greater than or equal to FROM + during spawn. This affects the subsequent file actions. */ +extern int +posix_spawn_file_actions_addclosefrom_np (posix_spawn_file_actions_t *, + int __from) + __THROW __nonnull ((1)); + #endif __END_DECLS diff --git a/posix/spawn_faction_addclosefrom.c b/posix/spawn_faction_addclosefrom.c new file mode 100644 index 0000000000..ff35b0519b --- /dev/null +++ b/posix/spawn_faction_addclosefrom.c @@ -0,0 +1,57 @@ +/* Add a closefrom to a file action list for posix_spawn. + 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 + +int +__posix_spawn_file_actions_addclosefrom (posix_spawn_file_actions_t + *file_actions, int from) +{ +#if __SPAWN_SUPPORT_CLOSEFROM + struct __spawn_action *rec; + + if (!__spawn_valid_fd (from)) + return EBADF; + + /* Allocate more memory if needed. */ + if (file_actions->__used == file_actions->__allocated + && __posix_spawn_file_actions_realloc (file_actions) != 0) + /* This can only mean we ran out of memory. */ + return ENOMEM; + + /* Add the new value. */ + rec = &file_actions->__actions[file_actions->__used]; + rec->tag = spawn_do_closefrom; + rec->action.closefrom_action.from = from; + + /* Account for the new entry. */ + ++file_actions->__used; + + return 0; +#else + return EINVAL; +#endif +} +weak_alias (__posix_spawn_file_actions_addclosefrom, + posix_spawn_file_actions_addclosefrom_np) +#if !__SPAWN_SUPPORT_CLOSEFROM +stub_warning (posix_spawn_file_actions_addclosefrom_np) +#endif diff --git a/posix/spawn_faction_destroy.c b/posix/spawn_faction_destroy.c index 7776f1a462..1a01b8e80e 100644 --- a/posix/spawn_faction_destroy.c +++ b/posix/spawn_faction_destroy.c @@ -39,6 +39,7 @@ __posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions) case spawn_do_close: case spawn_do_dup2: case spawn_do_fchdir: + case spawn_do_closefrom: /* No cleanup required. */ break; } diff --git a/posix/spawn_int.h b/posix/spawn_int.h index c579cb981d..81d43f2fa3 100644 --- a/posix/spawn_int.h +++ b/posix/spawn_int.h @@ -20,6 +20,7 @@ #define _SPAWN_INT_H #include +#include #include /* Data structure to contain the action information. */ @@ -32,6 +33,7 @@ struct __spawn_action spawn_do_open, spawn_do_chdir, spawn_do_fchdir, + spawn_do_closefrom, } tag; union @@ -60,6 +62,10 @@ struct __spawn_action { int fd; } fchdir_action; + struct + { + int from; + } closefrom_action; } action; }; diff --git a/posix/tst-spawn5.c b/posix/tst-spawn5.c new file mode 100644 index 0000000000..1e67d071b4 --- /dev/null +++ b/posix/tst-spawn5.c @@ -0,0 +1,284 @@ +/* Tests for posix_spawn signal handling. + 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 + +/* Nonzero if the program gets called via `exec'. */ +static int restart; + +/* Hold the four initial argument used to respawn the process, plus + the extra '--direct' and '--restart', and a final NULL. */ +static char *initial_argv[7]; + +#define CMDLINE_OPTIONS \ + { "restart", no_argument, &restart, 1 }, + +#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; +} + +/* Called on process re-execution. The arguments are the expected opened + file descriptors. */ +_Noreturn static void +handle_restart (int argc, char *argv[]) +{ + size_t nfds = argc > 1 ? argc - 1 : 0; + struct fd_t + { + int fd; + _Bool found; + } *fds = xmalloc (sizeof (struct fd_t) * nfds); + for (int i = 0; i < nfds; i++) + { + char *endptr; + long unsigned int fd = strtoul (argv[i+1], &endptr, 10); + if (*endptr != '\0' || fd > INT_MAX) + FAIL_EXIT1 ("readdir: invalid file descriptor value: %s", argv[i]); + + fds[i].fd = fd; + fds[i].found = false; + } + + DIR *dirp = opendir (FD_TO_FILENAME_PREFIX); + if (dirp == NULL) + FAIL_EXIT1 ("opendir (\"" FD_TO_FILENAME_PREFIX "\"): %m"); + + while (true) + { + errno = 0; + struct dirent64 *e = readdir64 (dirp); + if (e == NULL) + { + if (errno != 0) + FAIL_EXIT1 ("readdir: %m"); + break; + } + + if (e->d_name[0] == '.') + continue; + + char *endptr; + long int fd = strtol (e->d_name, &endptr, 10); + if (*endptr != '\0' || fd < 0 || fd > INT_MAX) + FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s", + e->d_name); + + /* Skip the descriptor which is used to enumerate the descriptors. */ + if (fd == dirfd (dirp) + || fd == STDIN_FILENO + || fd == STDOUT_FILENO + || fd == STDERR_FILENO) + continue; + + bool found = false; + for (int i = 0; i < nfds; i++) + if (fds[i].fd == fd) + fds[i].found = found = true; + + if (!found) + FAIL_EXIT1 ("unexpected open file descriptor: %ld", fd); + } + closedir (dirp); + + for (int i = 0; i < nfds; i++) + if (!fds[i].found) + FAIL_EXIT1 ("file descriptor %d not opened", fds[i].fd); + + free (fds); + + exit (EXIT_SUCCESS); +} + +static void +spawn_closefrom_test (posix_spawn_file_actions_t *fa, int lowfd, int highfd, + int *extrafds, size_t nextrafds) +{ + /* 6 elements from initial_argv (path to ld.so, '--library-path', the + path', application name', '--direct', and '--restart'), up to + 2 * maximum_fd arguments (the expected open file descriptors), plus + NULL. */ + enum { argv_size = array_length (initial_argv) + 2 * NFDS + 1 }; + char *args[argv_size]; + int argc = 0; + + for (char **arg = initial_argv; *arg != NULL; arg++) + args[argc++] = *arg; + + for (int i = lowfd; i < highfd; i++) + args[argc++] = xasprintf ("%d", i); + + for (int i = 0; i < nextrafds; i++) + args[argc++] = xasprintf ("%d", extrafds[i]); + + args[argc] = NULL; + TEST_VERIFY (argc < argv_size); + + pid_t pid; + int status; + + TEST_COMPARE (posix_spawn (&pid, args[0], fa, NULL, args, environ), 0); + TEST_COMPARE (xwaitpid (pid, &status, 0), pid); + TEST_VERIFY (WIFEXITED (status)); + TEST_VERIFY (!WIFSIGNALED (status)); + TEST_COMPARE (WEXITSTATUS (status), 0); +} + +static void +do_test_closefrom (void) +{ + int lowfd = open_multiple_temp_files (); + const int half_fd = lowfd + NFDS / 2; + + /* Close half of the descriptors and check result. */ + { + posix_spawn_file_actions_t fa; + TEST_COMPARE (posix_spawn_file_actions_init (&fa), 0); + + int ret = posix_spawn_file_actions_addclosefrom_np (&fa, half_fd); + if (ret == EINVAL) + /* Hurd currently does not support closefrom fileaction. */ + FAIL_UNSUPPORTED ("posix_spawn_file_actions_addclosefrom_np unsupported"); + TEST_COMPARE (ret, 0); + + spawn_closefrom_test (&fa, lowfd, half_fd, NULL, 0); + + TEST_COMPARE (posix_spawn_file_actions_destroy (&fa), 0); + } + + /* 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); + + { + posix_spawn_file_actions_t fa; + TEST_COMPARE (posix_spawn_file_actions_init (&fa), 0); + + TEST_COMPARE (posix_spawn_file_actions_addclosefrom_np (&fa, half_fd), 0); + + spawn_closefrom_test (&fa, lowfd, half_fd, NULL, 0); + + TEST_COMPARE (posix_spawn_file_actions_destroy (&fa), 0); + } + + /* Close the remaining but the last one. */ + { + posix_spawn_file_actions_t fa; + TEST_COMPARE (posix_spawn_file_actions_init (&fa), 0); + + TEST_COMPARE (posix_spawn_file_actions_addclosefrom_np (&fa, lowfd + 1), 0); + + spawn_closefrom_test (&fa, lowfd, lowfd + 1, NULL, 0); + + TEST_COMPARE (posix_spawn_file_actions_destroy (&fa), 0); + } + + /* Close everything. */ + { + posix_spawn_file_actions_t fa; + TEST_COMPARE (posix_spawn_file_actions_init (&fa), 0); + + TEST_COMPARE (posix_spawn_file_actions_addclosefrom_np (&fa, lowfd), 0); + + spawn_closefrom_test (&fa, lowfd, lowfd, NULL, 0); + + TEST_COMPARE (posix_spawn_file_actions_destroy (&fa), 0); + } + + /* Close a range and add some file actions. */ + { + posix_spawn_file_actions_t fa; + TEST_COMPARE (posix_spawn_file_actions_init (&fa), 0); + + TEST_COMPARE (posix_spawn_file_actions_addclosefrom_np (&fa, lowfd + 1), 0); + TEST_COMPARE (posix_spawn_file_actions_addopen (&fa, lowfd, "/dev/null", + 0666, O_RDONLY), 0); + TEST_COMPARE (posix_spawn_file_actions_adddup2 (&fa, lowfd, lowfd + 1), 0); + TEST_COMPARE (posix_spawn_file_actions_addopen (&fa, lowfd, "/dev/null", + 0666, O_RDONLY), 0); + + spawn_closefrom_test (&fa, lowfd, lowfd, (int[]){lowfd, lowfd + 1}, 2); + + TEST_COMPARE (posix_spawn_file_actions_destroy (&fa), 0); + } +} + +static int +do_test (int argc, char *argv[]) +{ + /* We must have either: + + - one or four parameters if called initially: + + argv[1]: path for ld.so optional + + argv[2]: "--library-path" optional + + argv[3]: the library path optional + + argv[4]: the application name + + - six parameters left if called through re-execution: + + argv[1]: the application name + + argv[2]: first expected open file descriptor + + argv[n]: last expected open file descritptor + + * When built with --enable-hardcoded-path-in-tests or issued without + using the loader directly. */ + + if (restart) + handle_restart (argc, argv); + + initial_argv[0] = argv[1]; /* path for ld.so */ + initial_argv[1] = argv[2]; /* "--library-path" */ + initial_argv[2] = argv[3]; /* the library path */ + initial_argv[3] = argv[4]; /* the application name */ + initial_argv[4] = (char *) "--direct"; + initial_argv[5] = (char *) "--restart"; + + do_test_closefrom (); + + return 0; +} + +#define TEST_FUNCTION_ARGV do_test +#include diff --git a/sysdeps/generic/spawn_int_def.h b/sysdeps/generic/spawn_int_def.h new file mode 100644 index 0000000000..ef6e03b1ef --- /dev/null +++ b/sysdeps/generic/spawn_int_def.h @@ -0,0 +1,24 @@ +/* Internal definitions for posix_spawn functionality. Generic 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 + . */ + +#ifndef _SPAWN_INT_DEF_H +#define _SPAWN_INT_DEF_H + +#define __SPAWN_SUPPORT_CLOSEFROM 0 + +#endif /* _SPAWN_INT_H */ diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist index 76d9e150f2..82c106e181 100644 --- a/sysdeps/mach/hurd/i386/libc.abilist +++ b/sysdeps/mach/hurd/i386/libc.abilist @@ -2229,6 +2229,7 @@ GLIBC_2.34 dlopen F GLIBC_2.34 dlsym F GLIBC_2.34 dlvsym F GLIBC_2.34 execveat F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 shm_open F GLIBC_2.34 shm_unlink F GLIBC_2.34 timespec_getres F diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c index b5c92365f2..e011c3b34b 100644 --- a/sysdeps/mach/hurd/spawni.c +++ b/sysdeps/mach/hurd/spawni.c @@ -613,6 +613,10 @@ retry: case spawn_do_fchdir: err = child_fchdir (action->action.fchdir_action.fd); break; + + case spawn_do_closefrom: + err = EINVAL; + break; } if (err) diff --git a/sysdeps/posix/spawni.c b/sysdeps/posix/spawni.c index fe3b5bb7f6..ad1858fe4e 100644 --- a/sysdeps/posix/spawni.c +++ b/sysdeps/posix/spawni.c @@ -231,6 +231,10 @@ __spawni_child (void *arguments) if (__fchdir (action->action.fchdir_action.fd) != 0) goto fail; break; + + case spawn_do_closefrom: + __set_errno (EINVAL); + goto fail; } } } diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist index e5ec01277d..4460b4078d 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2373,6 +2373,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist index 19f7a7fca4..71c5b11f62 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -2466,6 +2466,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist index ce6c13989a..ec81c56141 100644 --- a/sysdeps/unix/sysv/linux/arc/libc.abilist +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist @@ -2132,6 +2132,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist index 57e8456a3c..59256ad003 100644 --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist @@ -303,6 +303,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist index de42eccbba..d6f1607726 100644 --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist @@ -300,6 +300,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/closefrom.c b/sysdeps/unix/sysv/linux/closefrom.c index f5d7342c2c..372896b775 100644 --- a/sysdeps/unix/sysv/linux/closefrom.c +++ b/sysdeps/unix/sysv/linux/closefrom.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -29,7 +30,7 @@ __closefrom (int lowfd) if (r == 0) return; - if (!__closefrom_fallback (l)) + if (!__closefrom_fallback (l, true)) __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 index 61e71d388d..9cca55653a 100644 --- a/sysdeps/unix/sysv/linux/closefrom_fallback.c +++ b/sysdeps/unix/sysv/linux/closefrom_fallback.c @@ -22,9 +22,11 @@ #include /* Fallback code: iterates over /proc/self/fd, closing each file descriptor - that fall on the criteria. */ + that fall on the criteria. If DIRFD_FALLBACK is set, a failure on + /proc/self/fd open will trigger a fallback that tries to close a file + descriptor before proceed. */ _Bool -__closefrom_fallback (int from) +__closefrom_fallback (int from, _Bool dirfd_fallback) { bool ret = false; @@ -33,7 +35,7 @@ __closefrom_fallback (int from) if (dirfd == -1) { /* The closefrom should work even when process can't open new files. */ - if (errno == ENOENT) + if (errno == ENOENT || !dirfd_fallback) goto err; for (int i = from; i < INT_MAX; i++) diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist index f95d5ebbeb..fc7fff8fd5 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2392,6 +2392,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist index a9d7fb1a93..53a23e390a 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2346,6 +2346,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist index 1deab899b1..4d80b531b4 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2530,6 +2530,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist index 13121df7e0..16762122f8 100644 --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist @@ -2306,6 +2306,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist index e4fb78bf8e..0fb6adf535 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -304,6 +304,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist index b21d6b04af..77d731b270 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2473,6 +2473,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist index 7386b5360c..780be90942 100644 --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist @@ -2443,6 +2443,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist index c4c3f18e4d..7f915cfd11 100644 --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist @@ -2440,6 +2440,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist index b500aa4db3..97800b9f09 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2438,6 +2438,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist index 8260c3ba4f..7f4291c7c1 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2436,6 +2436,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist index b58b8eef2d..126ffc8431 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2444,6 +2444,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist index 3f19142fee..6445e7c407 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2362,6 +2362,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist index a1d7b0c25f..a573af9d9f 100644 --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist @@ -2482,6 +2482,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist index 1f81867311..842b466b3f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -2500,6 +2500,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist index 9f74a84ead..4dc6470c79 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -2533,6 +2533,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist index 8add515ff4..e5b0b746c1 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2270,6 +2270,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist index ab7489200b..412191fcd7 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2569,6 +2569,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist index 273c579b2d..d681b606e7 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -2134,6 +2134,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist index 9ae1c2ea89..053785d06f 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2334,6 +2334,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist index 622d19d754..7837ce9e95 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -2498,6 +2498,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist index 464e4cefde..78b99b9d25 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -2307,6 +2307,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist index d75a0ec228..655eec6150 100644 --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist @@ -2353,6 +2353,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist index 0eaeffda80..114b650965 100644 --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist @@ -2350,6 +2350,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist index 79e3d5a658..d3f3b83398 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -2491,6 +2491,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist index 727b767863..106a4a3296 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2327,6 +2327,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/spawn_int_def.h b/sysdeps/unix/sysv/linux/spawn_int_def.h new file mode 100644 index 0000000000..3be65b5711 --- /dev/null +++ b/sysdeps/unix/sysv/linux/spawn_int_def.h @@ -0,0 +1,25 @@ +/* Internal definitions for posix_spawn functionality. 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 + . */ + +#ifndef _SPAWN_INT_DEF_H +#define _SPAWN_INT_DEF_H + +/* spawni.c implements closefrom by interacting over /proc/self/fd. */ +#define __SPAWN_SUPPORT_CLOSEFROM 1 + +#endif /* _SPAWN_INT_H */ diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c index 3b435e6c86..403bf609df 100644 --- a/sysdeps/unix/sysv/linux/spawni.c +++ b/sysdeps/unix/sysv/linux/spawni.c @@ -16,22 +16,16 @@ 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 -#include -#include -#include -#include "spawn_int.h" +#include +#include +#include +#include /* The Linux implementation of posix_spawn{p} uses the clone syscall directly with CLONE_VM and CLONE_VFORK flags and an allocated stack. The new stack @@ -280,6 +274,14 @@ __spawni_child (void *arguments) if (__fchdir (action->action.fchdir_action.fd) != 0) goto fail; break; + + case spawn_do_closefrom: + { + int lowfd = action->action.closefrom_action.from; + int r = INLINE_SYSCALL_CALL (close_range, lowfd, ~0U, 0); + if (r != 0 && !__closefrom_fallback (lowfd, false)) + goto fail; + } break; } } } @@ -344,7 +346,9 @@ __spawnix (pid_t * pid, const char *file, /* We need at least a few pages in case the compiler's stack checking is enabled. In some configs, it is known to use at least 24KiB. We use 32KiB to be "safe" from anything the compiler might do. Besides, the - extra pages won't actually be allocated unless they get used. */ + extra pages won't actually be allocated unless they get used. + It also acts the slack for spawn_closefrom (including MIPS64 getdents64 + where it might use about 1k extra stack space. */ argv_size += (32 * 1024); size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize)); void *stack = __mmap (NULL, stack_size, prot, diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index fc84da9bae..00e31c04cd 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2285,6 +2285,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist index 2c44f71119..ed7e68ed4a 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2388,6 +2388,7 @@ GLIBC_2.34 mtx_lock F GLIBC_2.34 mtx_timedlock F GLIBC_2.34 mtx_trylock F GLIBC_2.34 mtx_unlock F +GLIBC_2.34 posix_spawn_file_actions_addclosefrom_np F GLIBC_2.34 pthread_attr_getaffinity_np F GLIBC_2.34 pthread_attr_getguardsize F GLIBC_2.34 pthread_attr_getstack F