From patchwork Sat May 22 03:50:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 43540 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 BEA303AAA0B6; Sat, 22 May 2021 03:50:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BEA303AAA0B6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1621655424; bh=dzXduyOwyTQjuxYgKTKVJs7yl12T91kKlB+VoAWZa8s=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=qNxMszXHLtRlpJ4/8mBNj+jwNw2OYz+xiwFCakEZPQ8+4paXzmmGnQtQTCVVaT3Aj JZsBQyEclcsvbncWj7Bxda9zYwmqg8on4ThdSmoCdNPNfBK2XKsA3B5F3kUtp67iXj iv+MqyBXpV2Uzx//8y3nhEIVD35fVaOb6VhoFSpQ= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432]) by sourceware.org (Postfix) with ESMTPS id 00E77383B409 for ; Sat, 22 May 2021 03:50:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 00E77383B409 Received: by mail-pf1-x432.google.com with SMTP id f22so7979097pfn.0 for ; Fri, 21 May 2021 20:50: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:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=dzXduyOwyTQjuxYgKTKVJs7yl12T91kKlB+VoAWZa8s=; b=f9JeKtS3PQrEzIf5u5Zw0U2ssAeub8p4MHGiJN8ufnwF31/KfHD4q2y8aTKWEVAP2Z gmhCU4kAVsfos8nmTOxyD2mjlY+xAMrk2C9zlkOTey2eFVUEqx9dG0NwMJb8g7id04as SZJNGb6NmTQw++GCH0fq+CxgW6/YgkaTXoJm+kDG+acrMDWr6tiHiYgBuCZq1V1fcsIx xXdzionHKA5m9sZaQV5aWifrIgZeODT6X39Js4Z6m81vhHRsf3RYe0nAWqha10dZAxiN fSr+Nu3EqJ4wYgOYfamZUM04ezmZUvCZsFy0a77SP8Pi4YapsX2rfV3BNfCC5KwPH4K0 EP/A== X-Gm-Message-State: AOAM531CLVSXW/rDAgEsEPuomhxBxjmiLrLJf8aNyWU23E/1qIjcYDzr SfsmHwyXX2+uxZslJoJuDw2hh3TcYebAPw== X-Google-Smtp-Source: ABdhPJw2bw0Gat9KVb9G6kdVbDi/b3Sm0hVIRzED2Qet8PhoTN7JgijhHAd7DsOwA/KqdzPG51dzfg== X-Received: by 2002:a63:ee10:: with SMTP id e16mr2047197pgi.135.1621655421133; Fri, 21 May 2021 20:50:21 -0700 (PDT) Received: from gnu-cfl-2.localdomain ([172.56.38.102]) by smtp.gmail.com with ESMTPSA id w124sm5377961pfb.73.2021.05.21.20.50.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 20:50:19 -0700 (PDT) Received: from gnu-cfl-2.. (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 3CC57C0387; Fri, 21 May 2021 20:50:18 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 1/5] Add cast_to_pointer to cast an integer to void * pointer Date: Fri, 21 May 2021 20:50:14 -0700 Message-Id: <20210522035018.2652112-2-hjl.tools@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210522035018.2652112-1-hjl.tools@gmail.com> References: <20210522035018.2652112-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3034.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, 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: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Cc: Florian Weimer Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" --- include/libc-pointer-arith.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/libc-pointer-arith.h b/include/libc-pointer-arith.h index 72e722c5aa..04ba537617 100644 --- a/include/libc-pointer-arith.h +++ b/include/libc-pointer-arith.h @@ -37,6 +37,9 @@ /* Cast an integer or a pointer VAL to integer with proper type. */ # define cast_to_integer(val) ((__integer_if_pointer_type (val)) (val)) +/* Cast an integer VAL to void * pointer. */ +# define cast_to_pointer(val) ((void *) (uintptr_t) (val)) + /* Align a value by rounding down to closest size. e.g. Using size of 4096, we get this behavior: {4095, 4096, 4097} = {0, 4096, 4096}. */ From patchwork Sat May 22 03:50:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 43543 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 D55FE3AAA0CD; Sat, 22 May 2021 03:50:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D55FE3AAA0CD DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1621655427; bh=J/KqdLMhc+IKu8aO1TRkA3bcxyEAJUkxx5s6ZnHwvlQ=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=WT4NB7ogLiRxlZ+byeaZ50uqxwyjokOtVZmeRVNi2SswXecyy6flyqWLi2sqGFlMs vYNLcOwCvK6CydEVBFgH35bGJ3bTpFQKBWk1plCbyQxWThb8drTDm/iKP8NnLbYS1O 8tcmB7sZxlnejkwBXIRP0lYf/8dNbjFjnRvT06Ng= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) by sourceware.org (Postfix) with ESMTPS id 409323AA9C29 for ; Sat, 22 May 2021 03:50:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 409323AA9C29 Received: by mail-pf1-x42a.google.com with SMTP id 10so16361238pfl.1 for ; Fri, 21 May 2021 20:50:23 -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:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=J/KqdLMhc+IKu8aO1TRkA3bcxyEAJUkxx5s6ZnHwvlQ=; b=hQ69esy+YQoMZdr3vbI3PQWlMqZjil3+AzxUz9/Vd2NCLegei2NMkRR63U5SF8mDFY dskHyZlPQBLlLjhV/sdICLEYP0BEiDIqnJFNfo3y01HQwXwDb9VJXFTnzMvG5d/5ORQy zVAzj/NoBafBEp8mX9C7BmZFKC5NFe+sgUaQwp6xeD7sOrjwsIYg6Q/CkSGqnN63/Khi uswLZ/P5jJSVIB4uFHyA1OJeOdarRNi6FIykG0abGEgZJgNDMQzYZvfMhgg/U1D0gqsP Q20xoVr1SJWL+8VTTiIcJUY+5AnPT46zNJwzAYLpslefz4jUrrIHYQ8i4ZA397yueCgM RvDg== X-Gm-Message-State: AOAM532qicGXt2F/3mK84pgEqYuzs/7khMMT278saj/6Yx9pnXAgxqiW qsyfQQHJ/GjhQkzoUO5pS/M= X-Google-Smtp-Source: ABdhPJxfcjNM5cwfYSZcw+zPSutVz7LZaAvEdXzYohooLAxZPhqiQuIKolRTJwGr3a2G67m/HhVebQ== X-Received: by 2002:a62:d447:0:b029:291:19f7:ddcd with SMTP id u7-20020a62d4470000b029029119f7ddcdmr13467013pfl.54.1621655422296; Fri, 21 May 2021 20:50:22 -0700 (PDT) Received: from gnu-cfl-2.localdomain ([172.56.38.102]) by smtp.gmail.com with ESMTPSA id s3sm5568816pfu.9.2021.05.21.20.50.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 20:50:19 -0700 (PDT) Received: from gnu-cfl-2.. (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 47B95C03D1; Fri, 21 May 2021 20:50:18 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 2/5] Add an internal wrapper for clone, clone2 and clone3 Date: Fri, 21 May 2021 20:50:15 -0700 Message-Id: <20210522035018.2652112-3-hjl.tools@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210522035018.2652112-1-hjl.tools@gmail.com> References: <20210522035018.2652112-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3034.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_NUMSUBJECT, 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: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Cc: Florian Weimer Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" The clone3 system call provides a superset of the functionality of clone and clone2. It also provides a number of API improvements, including the ability to specify the size of the child's stack area which can be used by kernel to compute the shadow stack size when allocating the shadow stack. Add: extern int __clone_internal (struct clone_args *__cl_args, int (*__func) (void *__arg), void *__arg); to provide an abstract interface for clone, clone2 and clone3. 1. Simplify stack management for thread creation by passing both stack base and size to create_thread. 2. Consolidate clone vs clone2 differences into a single file. 3. Use only __clone_internal to clone a thread. 4. Call __clone3 if HAVE_CLONE3_WAPPER is defined. If __clone3 returns -1 with ENOSYS, fall back to clone or clone2. 5. Enable the public clone3 wrapper in the future after it has been added to all targets. --- include/clone_internal.h | 16 +++++ sysdeps/unix/sysv/linux/Makefile | 2 +- sysdeps/unix/sysv/linux/clone-internal.c | 91 ++++++++++++++++++++++++ sysdeps/unix/sysv/linux/clone3.c | 1 + sysdeps/unix/sysv/linux/clone3.h | 60 ++++++++++++++++ sysdeps/unix/sysv/linux/createthread.c | 25 ++++--- sysdeps/unix/sysv/linux/spawni.c | 26 +++---- 7 files changed, 193 insertions(+), 28 deletions(-) create mode 100644 include/clone_internal.h create mode 100644 sysdeps/unix/sysv/linux/clone-internal.c create mode 100644 sysdeps/unix/sysv/linux/clone3.c create mode 100644 sysdeps/unix/sysv/linux/clone3.h diff --git a/include/clone_internal.h b/include/clone_internal.h new file mode 100644 index 0000000000..4b23ef33ce --- /dev/null +++ b/include/clone_internal.h @@ -0,0 +1,16 @@ +#ifndef _CLONE3_H +#include_next + +extern __typeof (clone3) __clone3; + +/* The internal wrapper of clone/clone2 and clone3. If __clone3 returns + -1 with ENOSYS, fall back to clone or clone2. */ +extern int __clone_internal (struct clone_args *__cl_args, + int (*__func) (void *__arg), void *__arg); + +#ifndef _ISOMAC +libc_hidden_proto (__clone3) +libc_hidden_proto (__clone_internal) +#endif + +#endif diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index fb155cf856..11b09345bc 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -64,7 +64,7 @@ sysdep_routines += adjtimex clone umount umount2 readahead sysctl \ time64-support pselect32 \ xstat fxstat lxstat xstat64 fxstat64 lxstat64 \ fxstatat fxstatat64 \ - xmknod xmknodat + xmknod xmknodat clone3 clone-internal CFLAGS-gethostid.c = -fexceptions CFLAGS-tee.c = -fexceptions -fasynchronous-unwind-tables diff --git a/sysdeps/unix/sysv/linux/clone-internal.c b/sysdeps/unix/sysv/linux/clone-internal.c new file mode 100644 index 0000000000..1e7a8f6b35 --- /dev/null +++ b/sysdeps/unix/sysv/linux/clone-internal.c @@ -0,0 +1,91 @@ +/* The internal wrapper of clone and clone3. + 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 /* For cast_to_pointer. */ +#include /* For _STACK_GROWS_{UP,DOWN}. */ + +#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */ +#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */ +#define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */ + +#define sizeof_field(TYPE, MEMBER) sizeof ((((TYPE *)0)->MEMBER)) +#define offsetofend(TYPE, MEMBER) \ + (offsetof (TYPE, MEMBER) + sizeof_field (TYPE, MEMBER)) + +_Static_assert (__alignof (struct clone_args) == 8, + "__alignof (struct clone_args) != 8"); +_Static_assert (offsetofend (struct clone_args, tls) == CLONE_ARGS_SIZE_VER0, + "offsetofend (struct clone_args, tls) != CLONE_ARGS_SIZE_VER0"); +_Static_assert (offsetofend (struct clone_args, set_tid_size) == CLONE_ARGS_SIZE_VER1, + "offsetofend (struct clone_args, set_tid_size) != CLONE_ARGS_SIZE_VER1"); +_Static_assert (offsetofend (struct clone_args, cgroup) == CLONE_ARGS_SIZE_VER2, + "offsetofend (struct clone_args, cgroup) != CLONE_ARGS_SIZE_VER2"); +_Static_assert (sizeof (struct clone_args) == CLONE_ARGS_SIZE_VER2, + "sizeof (struct clone_args) != CLONE_ARGS_SIZE_VER2"); + +int +__clone_internal (struct clone_args *cl_args, + int (*func) (void *arg), void *arg) +{ + int ret; +#ifdef HAVE_CLONE3_WAPPER + /* Try clone3 first. */ + int saved_errno = errno; + ret = __clone3 (cl_args, sizeof (*cl_args), func, arg); + if (ret != -1 || errno != ENOSYS) + return ret; + + /* NB: Restore errno since errno may be checked against non-zero + return value. */ + __set_errno (saved_errno); +#endif + + /* Map clone3 arguments to clone arguments. NB: No need to check + invalid clone3 specific bits in flags nor exit_signal since this + is an internal function. */ + int flags = cl_args->flags | cl_args->exit_signal; + void *stack = cast_to_pointer (cl_args->stack); + +#ifdef __ia64__ + ret = __clone2 (func, stack, cl_args->stack_size, + flags, arg, + cast_to_pointer (cl_args->parent_tid), + cast_to_pointer (cl_args->tls), + cast_to_pointer (cl_args->child_tid)); +#else +# if !_STACK_GROWS_DOWN && !_STACK_GROWS_UP +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +# endif + +# if _STACK_GROWS_DOWN + stack += cl_args->stack_size; +# endif + ret = __clone (func, stack, flags, arg, + cast_to_pointer (cl_args->parent_tid), + cast_to_pointer (cl_args->tls), + cast_to_pointer (cl_args->child_tid)); +#endif + return ret; +} + +libc_hidden_def (__clone_internal) diff --git a/sysdeps/unix/sysv/linux/clone3.c b/sysdeps/unix/sysv/linux/clone3.c new file mode 100644 index 0000000000..de963ef89d --- /dev/null +++ b/sysdeps/unix/sysv/linux/clone3.c @@ -0,0 +1 @@ +/* An empty placeholder. */ diff --git a/sysdeps/unix/sysv/linux/clone3.h b/sysdeps/unix/sysv/linux/clone3.h new file mode 100644 index 0000000000..0488884d59 --- /dev/null +++ b/sysdeps/unix/sysv/linux/clone3.h @@ -0,0 +1,60 @@ +/* The wrapper of clone3. + 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 _CLONE3_H +#define _CLONE3_H 1 + +#include +#include +#include + +__BEGIN_DECLS + +/* This struct should only be used in an argument to the clone3 system + call (along with its size argument). It may be extended with new + fields in the future. */ + +struct clone_args +{ + uint64_t flags; /* Flags bit mask. */ + uint64_t pidfd; /* Where to store PID file descriptor + (pid_t *). */ + uint64_t child_tid; /* Where to store child TID, in child's memory + (pid_t *). */ + uint64_t parent_tid; /* Where to store child TID, in parent's memory + (int *). */ + uint64_t exit_signal; /* Signal to deliver to parent on child + termination */ + uint64_t stack; /* The lowest address of stack. */ + uint64_t stack_size; /* Size of stack. */ + uint64_t tls; /* Location of new TLS. */ + uint64_t set_tid; /* Pointer to a pid_t array + (since Linux 5.5). */ + uint64_t set_tid_size; /* Number of elements in set_tid + (since Linux 5.5). */ + uint64_t cgroup; /* File descriptor for target cgroup + of child (since Linux 5.7). */ +} __attribute__ ((aligned (8))); + +/* The wrapper of clone3. */ +extern int clone3 (struct clone_args *__cl_args, size_t __size, + int (*__func) (void *__arg), void *__arg); + +__END_DECLS + +#endif /* clone3.h */ diff --git a/sysdeps/unix/sysv/linux/createthread.c b/sysdeps/unix/sysv/linux/createthread.c index bc3409b326..406c73ba00 100644 --- a/sysdeps/unix/sysv/linux/createthread.c +++ b/sysdeps/unix/sysv/linux/createthread.c @@ -25,15 +25,10 @@ #include #include #include +#include #include -#ifdef __NR_clone2 -# define ARCH_CLONE __clone2 -#else -# define ARCH_CLONE __clone -#endif - /* See the comments in pthread_create.c for the requirements for these two macros and the create_thread function. */ @@ -47,7 +42,8 @@ static int start_thread (void *arg) __attribute__ ((noreturn)); static int create_thread (struct pthread *pd, const struct pthread_attr *attr, - bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran) + bool *stopped_start, void *stackaddr, size_t stacksize, + bool *thread_ran) { /* Determine whether the newly created threads has to be started stopped since we have to set the scheduling parameters or set the @@ -100,9 +96,18 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr, TLS_DEFINE_INIT_TP (tp, pd); - if (__glibc_unlikely (ARCH_CLONE (&start_thread, STACK_VARIABLES_ARGS, - clone_flags, pd, &pd->tid, tp, &pd->tid) - == -1)) + struct clone_args args = + { + .flags = clone_flags, + .pidfd = (uintptr_t) &pd->tid, + .parent_tid = (uintptr_t) &pd->tid, + .child_tid = (uintptr_t) &pd->tid, + .stack = (uintptr_t) stackaddr, + .stack_size = stacksize, + .tls = (uintptr_t) tp, + }; + int ret = __clone_internal (&args, &start_thread, pd); + if (__glibc_unlikely (ret == -1)) return errno; /* It's started now, so if we fail below, we'll have to cancel it diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c index 501f8fbccd..fd29858cf5 100644 --- a/sysdeps/unix/sysv/linux/spawni.c +++ b/sysdeps/unix/sysv/linux/spawni.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "spawn_int.h" /* The Linux implementation of posix_spawn{p} uses the clone syscall directly @@ -59,21 +60,6 @@ normal program exit with the exit code 127. */ #define SPAWN_ERROR 127 -#ifdef __ia64__ -# define CLONE(__fn, __stackbase, __stacksize, __flags, __args) \ - __clone2 (__fn, __stackbase, __stacksize, __flags, __args, 0, 0, 0) -#else -# define CLONE(__fn, __stack, __stacksize, __flags, __args) \ - __clone (__fn, __stack, __flags, __args) -#endif - -/* Since ia64 wants the stackbase w/clone2, re-use the grows-up macro. */ -#if _STACK_GROWS_UP || defined (__ia64__) -# define STACK(__stack, __stack_size) (__stack) -#elif _STACK_GROWS_DOWN -# define STACK(__stack, __stack_size) (__stack + __stack_size) -#endif - struct posix_spawn_args { @@ -378,8 +364,14 @@ __spawnix (pid_t * pid, const char *file, need for CLONE_SETTLS. Although parent and child share the same TLS namespace, there will be no concurrent access for TLS variables (errno for instance). */ - new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size, - CLONE_VM | CLONE_VFORK | SIGCHLD, &args); + struct clone_args clone_args = + { + .flags = CLONE_VM | CLONE_VFORK, + .exit_signal = SIGCHLD, + .stack = (uintptr_t) stack, + .stack_size = stack_size, + }; + new_pid = __clone_internal (&clone_args, __spawni_child, &args); /* It needs to collect the case where the auxiliary process was created but failed to execute the file (due either any preparation step or From patchwork Sat May 22 03:50:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 43541 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 51C473AAA0C0; Sat, 22 May 2021 03:50:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 51C473AAA0C0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1621655425; bh=GMReAIqK14UlZIoFbURV6aQ+cqTifIFbiXaO85aOkyE=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=wkgcKP4TLmb9dbKmGj7q+7B4RN3pSSS97A48kPolO9X+PPxlqXQKIuU0gnTlVBIzP tcLGQHZB81IcZcG/6waIp8e8Dm9T0pC9GXA0nHr3qri2hSU/JzrXCZFaLz16zj9Nun OoF4ysS4GIBOpHuLC5YQ4O+ZjgB7WNsxh1gq92xw= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pj1-x102b.google.com (mail-pj1-x102b.google.com [IPv6:2607:f8b0:4864:20::102b]) by sourceware.org (Postfix) with ESMTPS id 892A838618BB for ; Sat, 22 May 2021 03:50:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 892A838618BB Received: by mail-pj1-x102b.google.com with SMTP id b9-20020a17090a9909b029015cf9effaeaso8326260pjp.5 for ; Fri, 21 May 2021 20:50: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:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GMReAIqK14UlZIoFbURV6aQ+cqTifIFbiXaO85aOkyE=; b=MIYtLWNLOcLAB/PphcO345aCSN2UAp41fXJ0/OrSMyvzcM3dHjn2ha6VZTwL0vj9MM OMuRxqAwaPOoSDobnjAw/EhVbndprbwgXY569YY49A2+Bf4WlVM87gxdZ75Fg9qSzTpd LKBdQns77Q4pK2CiYAjP+BfTgMtR9kKJSHtuLVJqOx0539d+yAJafAyU93jgtW1Tfo/W ZmbTrVsEanrzOXkk0h55E9VGXqYN2MWo6bbMlSH+eBynKkot33KgCwomarCuQ0U5yxAl Y9a3t9865U2O7wVyrKWcQbRD/A4qeVdxlG5uTxMt87abUtDi8URLWfWlLCzoyIA0DNTz 5mhQ== X-Gm-Message-State: AOAM533Fi0JYEQB9MUZEf0NgAAb7V+7OTu0fcdeafvFJMQyrJ9hny3+A G4ax8SA6WCwZC/1IrbboIumLqXWyQKRwng== X-Google-Smtp-Source: ABdhPJwLMVdUBFETHv8QsVHAyA2jLxzaskIOVSeOYw6Zpz/PfYTXc2cnvCIuN8K8p3D0GusmmuYzkA== X-Received: by 2002:a17:90a:e50e:: with SMTP id t14mr14364162pjy.101.1621655420665; Fri, 21 May 2021 20:50:20 -0700 (PDT) Received: from gnu-cfl-2.localdomain ([172.56.38.102]) by smtp.gmail.com with ESMTPSA id 30sm5624717pgo.7.2021.05.21.20.50.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 20:50:19 -0700 (PDT) Received: from gnu-cfl-2.. (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 52B5EC0415; Fri, 21 May 2021 20:50:18 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 3/5] nptl: Always pass stack size to create_thread Date: Fri, 21 May 2021 20:50:16 -0700 Message-Id: <20210522035018.2652112-4-hjl.tools@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210522035018.2652112-1-hjl.tools@gmail.com> References: <20210522035018.2652112-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3034.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, 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: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Cc: Florian Weimer Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Since the stack size argument for create_thread is now unconditional, always pass stack size to create_thread. --- nptl/allocatestack.c | 59 ++++--------------------------------------- nptl/createthread.c | 3 ++- nptl/pthread_create.c | 17 +++++++------ 3 files changed, 16 insertions(+), 63 deletions(-) diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index dc81a2ca73..eebf9c2c3c 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -33,47 +33,6 @@ #include #include -#ifndef NEED_SEPARATE_REGISTER_STACK - -/* Most architectures have exactly one stack pointer. Some have more. */ -# define STACK_VARIABLES void *stackaddr = NULL - -/* How to pass the values to the 'create_thread' function. */ -# define STACK_VARIABLES_ARGS stackaddr - -/* How to declare function which gets there parameters. */ -# define STACK_VARIABLES_PARMS void *stackaddr - -/* How to declare allocate_stack. */ -# define ALLOCATE_STACK_PARMS void **stack - -/* This is how the function is called. We do it this way to allow - other variants of the function to have more parameters. */ -# define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr) - -#else - -/* We need two stacks. The kernel will place them but we have to tell - the kernel about the size of the reserved address space. */ -# define STACK_VARIABLES void *stackaddr = NULL; size_t stacksize = 0 - -/* How to pass the values to the 'create_thread' function. */ -# define STACK_VARIABLES_ARGS stackaddr, stacksize - -/* How to declare function which gets there parameters. */ -# define STACK_VARIABLES_PARMS void *stackaddr, size_t stacksize - -/* How to declare allocate_stack. */ -# define ALLOCATE_STACK_PARMS void **stack, size_t *stacksize - -/* This is how the function is called. We do it this way to allow - other variants of the function to have more parameters. */ -# define ALLOCATE_STACK(attr, pd) \ - allocate_stack (attr, pd, &stackaddr, &stacksize) - -#endif - - /* Default alignment of stack. */ #ifndef STACK_ALIGN # define STACK_ALIGN __alignof__ (long double) @@ -249,7 +208,7 @@ advise_stack_range (void *mem, size_t size, uintptr_t pd, size_t guardsize) PDP must be non-NULL. */ static int allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, - ALLOCATE_STACK_PARMS) + void **stack, size_t *stacksize) { struct pthread *pd; size_t size; @@ -600,25 +559,17 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, /* We place the thread descriptor at the end of the stack. */ *pdp = pd; -#if _STACK_GROWS_DOWN void *stacktop; -# if TLS_TCB_AT_TP +#if TLS_TCB_AT_TP /* The stack begins before the TCB and the static TLS block. */ stacktop = ((char *) (pd + 1) - tls_static_size_for_stack); -# elif TLS_DTV_AT_TP +#elif TLS_DTV_AT_TP stacktop = (char *) (pd - 1); -# endif +#endif -# ifdef NEED_SEPARATE_REGISTER_STACK + *stacksize = stacktop - pd->stackblock; *stack = pd->stackblock; - *stacksize = stacktop - *stack; -# else - *stack = stacktop; -# endif -#else - *stack = pd->stackblock; -#endif return 0; } diff --git a/nptl/createthread.c b/nptl/createthread.c index 46943b33fe..2ac83111ec 100644 --- a/nptl/createthread.c +++ b/nptl/createthread.c @@ -25,7 +25,8 @@ static int create_thread (struct pthread *pd, const struct pthread_attr *attr, - bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran) + bool *stopped_start, void *stackaddr, size_t stacksize, + bool *thread_ran) { /* If the implementation needs to do some tweaks to the thread after it has been created at the OS level, it can set STOPPED_START here. */ diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index 5680687efe..5faf1654e0 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -243,8 +243,8 @@ late_init (void) be set to true iff the thread actually started up and then got canceled before calling user code (*PD->start_routine). */ static int create_thread (struct pthread *pd, const struct pthread_attr *attr, - bool *stopped_start, STACK_VARIABLES_PARMS, - bool *thread_ran); + bool *stopped_start, void *stackaddr, + size_t stacksize, bool *thread_ran); #include @@ -498,7 +498,8 @@ int __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { - STACK_VARIABLES; + void *stackaddr = NULL; + size_t stacksize = 0; /* Avoid a data race in the multi-threaded case, and call the deferred initialization only once. */ @@ -522,7 +523,7 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, } struct pthread *pd = NULL; - int err = ALLOCATE_STACK (iattr, &pd); + int err = allocate_stack (iattr, &pd, &stackaddr, &stacksize); int retval = 0; if (__glibc_unlikely (err != 0)) @@ -667,8 +668,8 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, /* We always create the thread stopped at startup so we can notify the debugger. */ - retval = create_thread (pd, iattr, &stopped_start, - STACK_VARIABLES_ARGS, &thread_ran); + retval = create_thread (pd, iattr, &stopped_start, stackaddr, + stacksize, &thread_ran); if (retval == 0) { /* We retain ownership of PD until (a) (see CONCURRENCY NOTES @@ -699,8 +700,8 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, } } else - retval = create_thread (pd, iattr, &stopped_start, - STACK_VARIABLES_ARGS, &thread_ran); + retval = create_thread (pd, iattr, &stopped_start, stackaddr, + stacksize, &thread_ran); /* Return to the previous signal mask, after creating the new thread. */ From patchwork Sat May 22 03:50:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 43542 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 4E7F23AAA0C5; Sat, 22 May 2021 03:50:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4E7F23AAA0C5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1621655427; bh=NFnw/idFnvnE3iSB1f8BcjWWhAcB1nhsuSndNwU6PoM=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=y0aW1B7qwy9J+WX373S024R8U7NriDFoDaWiXeDxc/AW3Y2ZpDT1V3+xFsDiV3tfb paa/GIPsula7QyJgUsa4tRQmFLzYhBgj7ZOdD6+8wXEeMkTUqeb0cpgP9361r/vNyi 7KOGW/uWWcWfCHM6iW6BZTIPEPEo4IDZo/vVxGFo= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by sourceware.org (Postfix) with ESMTPS id 8970E384605A for ; Sat, 22 May 2021 03:50:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8970E384605A Received: by mail-pj1-x1029.google.com with SMTP id kr9so3887421pjb.5 for ; Fri, 21 May 2021 20:50: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:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NFnw/idFnvnE3iSB1f8BcjWWhAcB1nhsuSndNwU6PoM=; b=LdiMNEbNCdJeKkLKimo56fl8NwPJKjaO0brHxszKaggqSUnSt66J9DIZSqvE9zMC4Z l17wkDfgNs9WlkiYLFmW4KdecgGV+092lAflHAsqfKSpWaHNj0Acq692Kkl8uX6krrwJ jpL0XNicv+fgghJk/EZyLpdBL7ho7R0eey3LUfGvSz7H4YhJKln2/63ygshRrJsPb+3M TxWnGZdbqjzG69OtGk3qfLX50JSbCU8cZoiAExaeiCITdMkJpzdH9RbFna/YUh9gE5bs 41Ltk+7gqYNaCwkOfZ5LDdEYEQQDc5v+nAwNvXeXa953bamqhyngQULsGmaRWQ+OE7IR PAKw== X-Gm-Message-State: AOAM530HwUE2P2OykXcf04RsGKK2WqsJPK2xWBazPOrB+fFPYOv8qaB4 s23bq+EEjNUtUatTDsBeoXc= X-Google-Smtp-Source: ABdhPJwvQcUjD9Q8zgr2nYqD4WBkye2McBr5yBQxzDJlQKJjqcmebYzMAY25VWhUt8xPHxvtqVG5xQ== X-Received: by 2002:a17:90a:e014:: with SMTP id u20mr14203773pjy.200.1621655421693; Fri, 21 May 2021 20:50:21 -0700 (PDT) Received: from gnu-cfl-2.localdomain ([172.56.38.102]) by smtp.gmail.com with ESMTPSA id 80sm5788276pgc.23.2021.05.21.20.50.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 20:50:19 -0700 (PDT) Received: from gnu-cfl-2.. (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 5DA7FC0468; Fri, 21 May 2021 20:50:18 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 4/5] x86-64: Add the clone3 wrapper Date: Fri, 21 May 2021 20:50:17 -0700 Message-Id: <20210522035018.2652112-5-hjl.tools@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210522035018.2652112-1-hjl.tools@gmail.com> References: <20210522035018.2652112-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3034.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, 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: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Cc: Florian Weimer Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" extern int clone3 (struct clone_args *__cl_args, size_t __size, int (*__func) (void *__arg), void *__arg); --- sysdeps/unix/sysv/linux/x86_64/clone3.S | 92 +++++++++++++++++++++++++ sysdeps/unix/sysv/linux/x86_64/sysdep.h | 2 + 2 files changed, 94 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/x86_64/clone3.S diff --git a/sysdeps/unix/sysv/linux/x86_64/clone3.S b/sysdeps/unix/sysv/linux/x86_64/clone3.S new file mode 100644 index 0000000000..71caaecc29 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86_64/clone3.S @@ -0,0 +1,92 @@ +/* The clone3 syscall wrapper. Linux/x86-64 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 + . */ + +/* clone3() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include + +/* The userland implementation is: + int clone3 (struct clone_args *cl_args, size_t size, + int (*func)(void *arg), void *arg); + the kernel entry is: + int clone3 (struct clone_args *cl_args, size_t size); + + The parameters are passed in registers from userland: + rdi: cl_args + rsi: size + rdx: func + rcx: arg + + The kernel expects: + rax: system call number + rdi: cl_args + rsi: size */ + + .text +ENTRY (__clone3) + /* Sanity check arguments. */ + movl $-EINVAL, %eax + test %RDI_LP, %RDI_LP /* No NULL cl_args pointer. */ + jz SYSCALL_ERROR_LABEL + test %RDX_LP, %RDX_LP /* No NULL function pointer. */ + jz SYSCALL_ERROR_LABEL + + /* Save the cl_args pointer in R8 which is preserved by the + syscall. */ + mov %RCX_LP, %R8_LP + + /* Do the system call. */ + movl $SYS_ify(clone3), %eax + + /* End FDE now, because in the child the unwind info will be + wrong. */ + cfi_endproc + syscall + + test %RAX_LP, %RAX_LP + jl SYSCALL_ERROR_LABEL + jz L(thread_start) + + ret + +L(thread_start): + cfi_startproc + /* Clearing frame pointer is insufficient, use CFI. */ + cfi_undefined (rip) + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp + + /* Align stack to 16 bytes per the x86-64 psABI. */ + and $-16, %RSP_LP + + /* Set up arguments for the function call. */ + mov %R8_LP, %RDI_LP /* Argument. */ + call *%rdx /* Call function. */ + /* Call exit with return value from function call. */ + movq %rax, %rdi + movl $SYS_ify(exit), %eax + syscall + cfi_endproc + + cfi_startproc +PSEUDO_END (__clone3) + +libc_hidden_def (__clone3) +weak_alias (__clone3, clone3) diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h index dbad2c788a..f26ffc68ae 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h @@ -377,6 +377,8 @@ # define HAVE_GETCPU_VSYSCALL "__vdso_getcpu" # define HAVE_CLOCK_GETRES64_VSYSCALL "__vdso_clock_getres" +# define HAVE_CLONE3_WAPPER 1 + # define SINGLE_THREAD_BY_GLOBAL 1 #endif /* __ASSEMBLER__ */ From patchwork Sat May 22 03:50:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 43544 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 8BE5A3AAA0D2; Sat, 22 May 2021 03:50:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8BE5A3AAA0D2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1621655429; bh=3k2wWbqzGUXVDwDOIivM+qYT5dZHO2761W2a27mXnn0=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=lASGHegIniM1i4Su30I7pKFktxRQCN8oUMqGfybIHdevoT58x9lttsnY7z0Ju3L0s QE8U9Xga908kiWIIpy+S7s6y+ZmRNhLy+8Gw+u019cWVCE7x34J9ZYvcR80YGoRI0U tQ1lt6jVDNPSJuSThSMPGOfFjX+zP9HObn/o5JHU= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by sourceware.org (Postfix) with ESMTPS id 5C016384605A for ; Sat, 22 May 2021 03:50:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 5C016384605A Received: by mail-pl1-x636.google.com with SMTP id 69so11978629plc.5 for ; Fri, 21 May 2021 20:50: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:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3k2wWbqzGUXVDwDOIivM+qYT5dZHO2761W2a27mXnn0=; b=VoAp61qS7zMV13iICOXyT0FFDIY4Ma5cuif6PoCfhQNHze3zbeweqc3DQZFo/KhfDI VVhYJRrPsLU9q0zqjYgnWajoSfXCsMaQCnOcFWBDFyTqFp1hQrN3i1CADR4ktua1nr7M S45euRE3/5XX3f8+x9BUd3FM1ZJ/ZTkDA1776GrQe3VzJIZTuD8RJB701+XZa/vn9KRR zd8QQvw/x5l5nJJuPFIgiF3W5Xk+03hv8qj1yhF3TVrCpnBkukgk+iYBJyJryYIx14Zt A+/o+o53HZegAn2mRCzw0c1ZbgWoU5VcdW4kPbJLrb1oK+qlBri7Pdq7O6G54LkIp4tc MKCw== X-Gm-Message-State: AOAM5314/iJyBm5J8sUOM5Dp6iQQ+nPQTuYuHnJUdlGdkk0uKsiuPHyq mpjRSgM/6mr1UcUbndDxKMSZD+wu9o8p2g== X-Google-Smtp-Source: ABdhPJzUafutUlItmDRFg6VPZN2FiS+fKmDpB7LpAt2JVDJX67z8MTuJ7YygnvAxbqjzJau57bytvw== X-Received: by 2002:a17:902:b408:b029:ec:e879:bbd8 with SMTP id x8-20020a170902b408b02900ece879bbd8mr15568207plr.65.1621655423427; Fri, 21 May 2021 20:50:23 -0700 (PDT) Received: from gnu-cfl-2.localdomain ([172.56.38.102]) by smtp.gmail.com with ESMTPSA id a10sm9426276pjs.39.2021.05.21.20.50.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 May 2021 20:50:22 -0700 (PDT) Received: from gnu-cfl-2.. (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 68BD9C04B5; Fri, 21 May 2021 20:50:18 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v6 5/5] Add static tests for __clone_internal Date: Fri, 21 May 2021 20:50:18 -0700 Message-Id: <20210522035018.2652112-6-hjl.tools@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210522035018.2652112-1-hjl.tools@gmail.com> References: <20210522035018.2652112-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3035.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, 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: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Cc: Florian Weimer Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" --- sysdeps/unix/sysv/linux/Makefile | 8 + .../sysv/linux/tst-align-clone-internal.c | 86 +++++++++++ sysdeps/unix/sysv/linux/tst-clone2-internal.c | 137 ++++++++++++++++++ sysdeps/unix/sysv/linux/tst-clone3-internal.c | 99 +++++++++++++ .../unix/sysv/linux/tst-getpid1-internal.c | 132 +++++++++++++++++ 5 files changed, 462 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/tst-align-clone-internal.c create mode 100644 sysdeps/unix/sysv/linux/tst-clone2-internal.c create mode 100644 sysdeps/unix/sysv/linux/tst-clone3-internal.c create mode 100644 sysdeps/unix/sysv/linux/tst-getpid1-internal.c diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 11b09345bc..9bcd38a732 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -118,6 +118,14 @@ endif tests-internal += tst-sigcontext-get_pc +tests-clone-internal = \ + tst-align-clone-internal \ + tst-clone2-internal \ + tst-clone3-internal \ + tst-getpid1-internal +tests-internal += $(tests-clone-internal) +tests-static += $(tests-clone-internal) + CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables # Generate the list of SYS_* macros for the system calls (__NR_* diff --git a/sysdeps/unix/sysv/linux/tst-align-clone-internal.c b/sysdeps/unix/sysv/linux/tst-align-clone-internal.c new file mode 100644 index 0000000000..0e5307a033 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-align-clone-internal.c @@ -0,0 +1,86 @@ +/* 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 + +static int +f (void *arg) +{ + bool ok = true; + + puts ("in f"); + + if (TEST_STACK_ALIGN ()) + ok = false; + + return ok ? 0 : 1; +} + +static int +do_test (void) +{ + bool ok = true; + + puts ("in main"); + + if (TEST_STACK_ALIGN ()) + ok = false; + +#ifdef __ia64__ +# define STACK_SIZE 256 * 1024 +#else +# define STACK_SIZE 128 * 1024 +#endif + char st[STACK_SIZE] __attribute__ ((aligned)); + struct clone_args clone_args = + { + .stack = (uintptr_t) st, + .stack_size = sizeof (st), + }; + pid_t p = __clone_internal (&clone_args, f, 0); + if (p == -1) + { + printf("clone failed: %m\n"); + return 1; + } + + int e; + xwaitpid (p, &e, __WCLONE); + if (!WIFEXITED (e)) + { + if (WIFSIGNALED (e)) + printf ("died from signal %s\n", strsignal (WTERMSIG (e))); + else + puts ("did not terminate correctly"); + return 1; + } + if (WEXITSTATUS (e) != 0) + ok = false; + + return ok ? 0 : 1; +} + +#include diff --git a/sysdeps/unix/sysv/linux/tst-clone2-internal.c b/sysdeps/unix/sysv/linux/tst-clone2-internal.c new file mode 100644 index 0000000000..b8917fe713 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-clone2-internal.c @@ -0,0 +1,137 @@ +/* Test if CLONE_VM does not change pthread pid/tid field (BZ #19957) + 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 +#include + +static int sig; +static int pipefd[2]; + +static int +f (void *a) +{ + close (pipefd[0]); + + pid_t ppid = getppid (); + pid_t pid = getpid (); + pid_t tid = gettid (); + + if (write (pipefd[1], &ppid, sizeof ppid) != sizeof (ppid)) + FAIL_EXIT1 ("write ppid failed\n"); + if (write (pipefd[1], &pid, sizeof pid) != sizeof (pid)) + FAIL_EXIT1 ("write pid failed\n"); + if (write (pipefd[1], &tid, sizeof tid) != sizeof (tid)) + FAIL_EXIT1 ("write tid failed\n"); + + return 0; +} + + +static int +do_test (void) +{ + sig = SIGRTMIN; + sigset_t ss; + sigemptyset (&ss); + sigaddset (&ss, sig); + if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0) + FAIL_EXIT1 ("sigprocmask failed: %m"); + + if (pipe2 (pipefd, O_CLOEXEC)) + FAIL_EXIT1 ("pipe failed: %m"); + +#ifdef __ia64__ +# define STACK_SIZE 256 * 1024 +#else +# define STACK_SIZE 128 * 1024 +#endif + char st[STACK_SIZE] __attribute__ ((aligned)); + struct clone_args clone_args = + { + .stack = (uintptr_t) st, + .stack_size = sizeof (st), + }; + pid_t p = __clone_internal (&clone_args, f, 0); + + close (pipefd[1]); + + if (p == -1) + FAIL_EXIT1("clone failed: %m"); + + pid_t ppid, pid, tid; + if (read (pipefd[0], &ppid, sizeof pid) != sizeof pid) + { + kill (p, SIGKILL); + FAIL_EXIT1 ("read ppid failed: %m"); + } + if (read (pipefd[0], &pid, sizeof pid) != sizeof pid) + { + kill (p, SIGKILL); + FAIL_EXIT1 ("read pid failed: %m"); + } + if (read (pipefd[0], &tid, sizeof tid) != sizeof tid) + { + kill (p, SIGKILL); + FAIL_EXIT1 ("read tid failed: %m"); + } + + close (pipefd[0]); + + int ret = 0; + + pid_t own_pid = getpid (); + pid_t own_tid = syscall (__NR_gettid); + + /* Some sanity checks for clone syscall: returned ppid should be current + pid and both returned tid/pid should be different from current one. */ + if ((ppid != own_pid) || (pid == own_pid) || (tid == own_tid)) + FAIL_RET ("ppid=%i pid=%i tid=%i | own_pid=%i own_tid=%i", + (int)ppid, (int)pid, (int)tid, (int)own_pid, (int)own_tid); + + int e; + xwaitpid (p, &e, __WCLONE); + if (!WIFEXITED (e)) + { + if (WIFSIGNALED (e)) + printf ("died from signal %s\n", strsignal (WTERMSIG (e))); + else + puts ("did not terminate correctly"); + exit (EXIT_FAILURE); + } + if (WEXITSTATUS (e) != 0) + FAIL_EXIT1 ("exit code %d", WEXITSTATUS (e)); + + return ret; +} + +#include diff --git a/sysdeps/unix/sysv/linux/tst-clone3-internal.c b/sysdeps/unix/sysv/linux/tst-clone3-internal.c new file mode 100644 index 0000000000..2bdbc571e6 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-clone3-internal.c @@ -0,0 +1,99 @@ +/* Check if clone (CLONE_THREAD) does not call exit_group (BZ #21512) + 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 + +/* Test if clone call with CLONE_THREAD does not call exit_group. The 'f' + function returns '1', which will be used by clone thread to call the + 'exit' syscall directly. If _exit is used instead, exit_group will be + used and thus the thread group will finish with return value of '1' + (where '2' from main thread is expected.). */ + +static int +f (void *a) +{ + return 1; +} + +/* Futex wait for TID argument, similar to pthread_join internal + implementation. */ +#define wait_tid(ctid_ptr, ctid_val) \ + do { \ + __typeof (*(ctid_ptr)) __tid; \ + /* We need acquire MO here so that we synchronize with the \ + kernel's store to 0 when the clone terminates. */ \ + while ((__tid = atomic_load_explicit (ctid_ptr, \ + memory_order_acquire)) != 0) \ + futex_wait (ctid_ptr, ctid_val); \ + } while (0) + +static inline int +futex_wait (int *futexp, int val) +{ +#ifdef __NR_futex + return syscall (__NR_futex, futexp, FUTEX_WAIT, val); +#else + return syscall (__NR_futex_time64, futexp, FUTEX_WAIT, val); +#endif +} + +static int +do_test (void) +{ + char st[1024] __attribute__ ((aligned)); + int clone_flags = CLONE_THREAD; + /* Minimum required flags to used along with CLONE_THREAD. */ + clone_flags |= CLONE_VM | CLONE_SIGHAND; + /* We will used ctid to call on futex to wait for thread exit. */ + clone_flags |= CLONE_CHILD_CLEARTID; + /* Initialize with a known value. ctid is set to zero by the kernel after the + cloned thread has exited. */ +#define CTID_INIT_VAL 1 + pid_t ctid = CTID_INIT_VAL; + pid_t tid; + + struct clone_args clone_args = + { + .flags = clone_flags & ~CSIGNAL, + .exit_signal = clone_flags & CSIGNAL, + .stack = (uintptr_t) st, + .stack_size = sizeof (st), + .child_tid = (uintptr_t) &ctid, + }; + tid = __clone_internal (&clone_args, f, NULL); + if (tid == -1) + FAIL_EXIT1 ("clone failed: %m"); + + wait_tid (&ctid, CTID_INIT_VAL); + + return 2; +} + +#define EXPECTED_STATUS 2 +#include diff --git a/sysdeps/unix/sysv/linux/tst-getpid1-internal.c b/sysdeps/unix/sysv/linux/tst-getpid1-internal.c new file mode 100644 index 0000000000..5ce091168e --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-getpid1-internal.c @@ -0,0 +1,132 @@ +/* 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 + +#ifndef TEST_CLONE_FLAGS +#define TEST_CLONE_FLAGS 0 +#endif + +static int sig; + +static int +f (void *a) +{ + puts ("in f"); + union sigval sival; + sival.sival_int = getpid (); + printf ("pid = %d\n", sival.sival_int); + if (sigqueue (getppid (), sig, sival) != 0) + return 1; + return 0; +} + + +static int +do_test (void) +{ + int mypid = getpid (); + + sig = SIGRTMIN; + sigset_t ss; + sigemptyset (&ss); + sigaddset (&ss, sig); + if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0) + { + printf ("sigprocmask failed: %m\n"); + return 1; + } + +#ifdef __ia64__ +# define STACK_SIZE 256 * 1024 +#else +# define STACK_SIZE 128 * 1024 +#endif + char st[STACK_SIZE] __attribute__ ((aligned)); + struct clone_args clone_args = + { + .flags = TEST_CLONE_FLAGS & ~CSIGNAL, + .exit_signal = TEST_CLONE_FLAGS & CSIGNAL, + .stack = (uintptr_t) st, + .stack_size = sizeof (st), + }; + pid_t p = __clone_internal (&clone_args, f, 0); + if (p == -1) + { + printf("clone failed: %m\n"); + return 1; + } + printf ("new thread: %d\n", (int) p); + + siginfo_t si; + do + if (sigwaitinfo (&ss, &si) < 0) + { + printf("sigwaitinfo failed: %m\n"); + kill (p, SIGKILL); + return 1; + } + while (si.si_signo != sig || si.si_code != SI_QUEUE); + + int e; + xwaitpid (p, &e, __WCLONE); + if (!WIFEXITED (e)) + { + if (WIFSIGNALED (e)) + printf ("died from signal %s\n", strsignal (WTERMSIG (e))); + else + puts ("did not terminate correctly"); + return 1; + } + if (WEXITSTATUS (e) != 0) + { + printf ("exit code %d\n", WEXITSTATUS (e)); + return 1; + } + + if (si.si_int != (int) p) + { + printf ("expected PID %d, got si_int %d\n", (int) p, si.si_int); + kill (p, SIGKILL); + return 1; + } + + if (si.si_pid != p) + { + printf ("expected PID %d, got si_pid %d\n", (int) p, (int) si.si_pid); + kill (p, SIGKILL); + return 1; + } + + if (getpid () != mypid) + { + puts ("my PID changed"); + return 1; + } + + return 0; +} + +#include