From patchwork Sat Oct 28 19:55:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 738986 Delivered-To: patch@linaro.org Received: by 2002:a5d:4c47:0:b0:32d:baff:b0ca with SMTP id n7csp482881wrt; Sat, 28 Oct 2023 12:56:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGh64kcpJUXkp/6lgQKjnJa/k36l4yoqXIm2qLcPP1nssaAq6Df7LLhJXb95Sc8ut1JZCz6 X-Received: by 2002:a05:6214:d02:b0:65b:21c8:2d74 with SMTP id 2-20020a0562140d0200b0065b21c82d74mr7258762qvh.6.1698523011583; Sat, 28 Oct 2023 12:56:51 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1698523011; cv=pass; d=google.com; s=arc-20160816; b=d4j07vc8ftg1warzLohqNj91Hrgd3LItQUqp2U1oIsUEH74vQPqGIuyvOUsupRWtkm VqeuHa3UJxSJKsLGlojqfOeiV4cQ/4jltmwZoLD0OuOs8mazjeBHovfay63JiTaUiTYO W02Lhgfw4yjeQ8Rl52Su0fW1pmvgjiOJ9o2pf0OtRK0+/f+bMIcvii83F/b3kCS+8238 Ht//V2OyTNnvCVvNA56T/ZoubfPw5TOXOKEKnZa+fzVdz/b0e++P7uscuaVp5nOD7oWG m0Nv2XBQU2GV90RHcSLMbOOEUBX454FmOudqvR1zaFUPEwxrFV8FbfNNfTtzpxbKY5L5 4VQw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=utSWdvQl98iM9LBNL1svLmWLEXYk5MyyPql06V1kCt4=; fh=Lbqp+rs2mRBTG5C9ik7cirOzlOF2+U9yLxjtEQVqExY=; b=M6zOwJCvoNTcLadcOnqcKUPHn5uVXvT1hmhm4HExfPC9muifAx57jM2RGy4KzPC/k3 11nC9XEMA0k9zvjhZ3uGXXwE+cQs0JdPF37zsZvamulupNwlXEF3NVkClC1AsT7qlXpC vASk/QCJlfTAceKjjVC5cXmZdfrArovHW5Joss8Ds/nDhvqWBAtMIiXOiVETfzeENj2B KRnFV2F2yrHGecUhMkxCEhAidN4igh4UiYskAt0asZLTkNvPUFN8Hw5pVbmpqmdBOcBp K64+l6BcDk7CxkuvAfFfyIxRaMvR8qmOfwBtChNUjruNPUFxLhYWUlX9Kt4c+gh/mLLS qU9w== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Z/mWilEO"; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces+patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="libc-alpha-bounces+patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id w14-20020a05622a134e00b004181f579652si2877157qtk.118.2023.10.28.12.56.51 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 28 Oct 2023 12:56:51 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-bounces+patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Z/mWilEO"; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces+patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="libc-alpha-bounces+patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4142138618C2 for ; Sat, 28 Oct 2023 19:56:51 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-ot1-x331.google.com (mail-ot1-x331.google.com [IPv6:2607:f8b0:4864:20::331]) by sourceware.org (Postfix) with ESMTPS id 1A6FD38618E5 for ; Sat, 28 Oct 2023 19:56:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1A6FD38618E5 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1A6FD38618E5 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::331 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698522978; cv=none; b=xQQIzacnD6eO5efvQVPgRGHVgnVVPZJjWnqX5NWQlnJhQ9ryn/WUA9rJKRNeKx1STrQCpLMU+m1NbsE7A5cuSd4xdpNCeC2jj1IOcUpHSKLGGxU+ozh2vjqbOga+snlOe9UCJlcchMy+2yi8RnVQ3im5lvDoyOz52JDpJcO0lug= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698522978; c=relaxed/simple; bh=jTwbbxK6coyBuUNDI/1hQ7nwGzS5N7M/TZQfOn2Dvtc=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=Zyr/Wc0oaaLelCcX6c+t3lcToG08DUWeUjHKZYyG60J3qP8LTSmJ1h/9C17JwNd1TmIF6gJCQHhJ3slaFic6JmB4ymwr7WefiDjfLOLc0LE2NS5SCDp5l7WrB4Tl6DIWXa9zq0hEzeNEiZjid0ET1GPft05aAmiY6BMOBXZmxUs= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-ot1-x331.google.com with SMTP id 46e09a7af769-6ce2988d62eso2121090a34.1 for ; Sat, 28 Oct 2023 12:56:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698522974; x=1699127774; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=utSWdvQl98iM9LBNL1svLmWLEXYk5MyyPql06V1kCt4=; b=Z/mWilEOvJgjQaYqesm1KqpjHOs2WUFny1HPTGyFkIR4jBQjrc2ebMYwDxf6yEhcWd 6ZOcxnIxdL5aQm17wvCkvr1eVbmRomgPS9Y7ZtCE6l3LlOi9+6lWZ1+3eNXUSv+5kceQ P+ZwTsC2qdBAM5PyeVdZfE6cif097wI/DwOedq5eHSH+Ka/Q3aKNOLcUGhGEFKWcuMNp JCSRlz1yYRv7upISgaQMh/momEQv+mjkz/daad/bS+wiO1NQPqoRPaiZ2kRRqrtCv/yn QWhzsUF3J62eZDKufU4tb1cIfYQj+bEsXogZfmWfGgv0ucGDSINnm6Aap+JIAzUCBSFy JkBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698522974; x=1699127774; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=utSWdvQl98iM9LBNL1svLmWLEXYk5MyyPql06V1kCt4=; b=QIucnYOVxixX4plLxm9+gYN4xEjh/Prl0aBtQYGzDCy2EFkqFEuCrvp4q+RJFqxSy7 Xh7+fBFQUR4LsLkKXyRGFyhxdJaX4d1im8ORh60a8H1nsSRh+cpldD9zjn3miDcqCrhy irlDmk7H685+f4YH+SJqhzqqQ2KQvKA1NnBpzRiX3JeP5RibPFH9IMnY44SFCdN3J/JN STB//3FMYWF6/BphCN/tzHspivBRvWuukNKyNRx9XH2r+tYql4qdctW9DSn+FqKQV+6P YWyji3h/aRXFPYySdaxnHl+nbPFlv/iGOA+L0Uwz8R185uu/7fTujwZxJDHIktSQsKBU iUTg== X-Gm-Message-State: AOJu0YzJlSmCu7SqN79NWB6cCtqBMnDMD9f9yyHvlsi5ysWYpwqIb1So Ki7a3mm+UYK9jtysVL78drr23qK+xfFKqrzbBjjZiorB X-Received: by 2002:a9d:7499:0:b0:6b9:1917:b2f3 with SMTP id t25-20020a9d7499000000b006b91917b2f3mr6407618otk.33.1698522974638; Sat, 28 Oct 2023 12:56:14 -0700 (PDT) Received: from localhost.localdomain ([139.178.84.207]) by smtp.gmail.com with ESMTPSA id w20-20020a056830411400b006b8c87551e8sm763181ott.35.2023.10.28.12.56.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 28 Oct 2023 12:56:13 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org, Ian Rogers , Francesco Nigro , Carlos O'Donell , Siddhesh Poyarekar Subject: [PATCH v2 3/7] nptl: Decorate thread stack on pthread_create Date: Sat, 28 Oct 2023 19:55:55 +0000 Message-Id: <20231028195559.390407-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231028195559.390407-1-adhemerval.zanella@linaro.org> References: <20231028195559.390407-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patch=linaro.org@sourceware.org Linux 4.5 removed thread stack annotations due to the complexity of computing them [1], and Linux added PR_SET_VMA_ANON_NAME on 5.17 as a way to name anonymous virtual memory areas. This patch adds decoration on the stack created and used by pthread_create, for glibc crated thread stack the /proc/self/maps will now show: [anon: glibc: pthread stack: ] And for user-provided stacks: [anon: glibc: pthread user stack: ] The guard page is not decorated, and the mapping name is cleared when the thread finishes its execution (so the cached stack does not have any name associated). Co-authored-by: Ian Rogers Checked on x86_64-linux-gnu aarch64 aarch64-linux-gnu. [1] https://github.com/torvalds/linux/commit/65376df582174ffcec9e6471bf5b0dd79ba05e4a Reviewed-by: DJ Delorie --- elf/Makefile | 3 + elf/tst-decorate-maps.c | 160 ++++++++++++++++++++++++++++++++++++++++ nptl/allocatestack.c | 40 ++++++++++ nptl/pthread_create.c | 6 ++ 4 files changed, 209 insertions(+) create mode 100644 elf/tst-decorate-maps.c diff --git a/elf/Makefile b/elf/Makefile index 9176cbf1e3..a82590703c 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -303,6 +303,7 @@ tests := \ tst-array4 \ tst-array5 \ tst-auxv \ + tst-decorate-maps \ tst-dl-hash \ tst-leaks1 \ tst-stringtable \ @@ -3018,3 +3019,5 @@ LDFLAGS-tst-dlclose-lazy-mod1.so = -Wl,-z,lazy,--no-as-needed $(objpfx)tst-dlclose-lazy-mod1.so: $(objpfx)tst-dlclose-lazy-mod2.so $(objpfx)tst-dlclose-lazy.out: \ $(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so + +$(objpfx)tst-decorate-maps: $(shared-thread-library) diff --git a/elf/tst-decorate-maps.c b/elf/tst-decorate-maps.c new file mode 100644 index 0000000000..bbb7972094 --- /dev/null +++ b/elf/tst-decorate-maps.c @@ -0,0 +1,160 @@ +/* Check the VMA name decoration. + Copyright (C) 2023 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 MAP_STACK +# define MAP_STACK 0 +#endif + +static pthread_barrier_t b; + +static void * +tf (void *closure) +{ + /* Wait the thread startup, so thread stack is allocated. */ + xpthread_barrier_wait (&b); + + /* Wait the test to read the process mapiping. */ + xpthread_barrier_wait (&b); + + return NULL; +} + +struct proc_maps_t +{ + int n_def_threads; + int n_user_threads; +}; + +static struct proc_maps_t +read_proc_maps (void) +{ + if (test_verbose) + printf ("=== print process %jd memory mapping ===\n", + (intmax_t) getpid ()); + struct proc_maps_t r = { 0 }; + + FILE *f = xfopen ("/proc/self/maps", "r"); + char *line = NULL; + size_t line_len = 0; + while (xgetline (&line, &line_len, f)) + { + if (test_verbose) + printf ("%s", line); + if (strstr (line, "[anon: glibc: pthread stack:") != NULL) + r.n_def_threads++; + else if (strstr (line, "[anon: glibc: pthread user stack:") != NULL) + r.n_user_threads++; + } + free (line); + xfclose (f); + + if (test_verbose) + printf ("===\n"); + return r; +} + +static void +do_test_threads (bool set_guard) +{ + enum + { + num_def_threads = 8, + num_user_threads = 2, + num_threads = num_def_threads + num_user_threads, + }; + + xpthread_barrier_init (&b, NULL, num_threads + 1); + + pthread_t thr[num_threads]; + { + int i = 0; + for (; i < num_threads - num_user_threads; i++) + { + pthread_attr_t attr; + xpthread_attr_init (&attr); + /* The guard page is not annotated. */ + if (!set_guard) + xpthread_attr_setguardsize (&attr, 0); + thr[i] = xpthread_create (&attr, tf, NULL); + xpthread_attr_destroy (&attr); + } + for (; i < num_threads; i++) + { + pthread_attr_t attr; + xpthread_attr_init (&attr); + size_t stacksize = support_small_thread_stack_size (); + void *stack = xmmap (0, + stacksize, + PROT_READ | PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, + -1); + xpthread_attr_setstack (&attr, stack, stacksize); + if (!set_guard) + xpthread_attr_setguardsize (&attr, 0); + thr[i] = xpthread_create (&attr, tf, NULL); + xpthread_attr_destroy (&attr); + } + } + + /* Wait all threads to finshed statup and stack allocation. */ + xpthread_barrier_wait (&b); + + { + struct proc_maps_t r = read_proc_maps (); + TEST_COMPARE (r.n_def_threads, num_def_threads); + TEST_COMPARE (r.n_user_threads, num_user_threads); + } + + /* Let the threads finish. */ + xpthread_barrier_wait (&b); + + for (int i = 0; i < num_threads; i++) + xpthread_join (thr[i]); + + { + struct proc_maps_t r = read_proc_maps (); + TEST_COMPARE (r.n_def_threads, 0); + TEST_COMPARE (r.n_user_threads, 0); + } +} + +static int +do_test (void) +{ + support_need_proc ("Reads /proc/self/maps to get stack names."); + + if (!support_set_vma_name ()) + FAIL_UNSUPPORTED ("kernel does not support PR_SET_VMA_ANON_NAME"); + + do_test_threads (false); + do_test_threads (true); + + return 0; +} + +#include diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index f9d8cdfd08..97d0efec10 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include /* Default alignment of stack. */ #ifndef STACK_ALIGN @@ -577,3 +579,41 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, return 0; } + +/* Maximum supported name from initial kernel support, not exported + by user API. */ +#define ANON_VMA_NAME_MAX_LEN 80 + +#define SET_STACK_NAME(__prefix, __stack, __stacksize, __tid) \ + ({ \ + char __stack_name[sizeof (__prefix) + \ + INT_BUFSIZE_BOUND (unsigned int)]; \ + _Static_assert (sizeof __stack_name <= ANON_VMA_NAME_MAX_LEN, \ + "VMA name size larger than maximum supported"); \ + __snprintf (__stack_name, sizeof (__stack_name), __prefix "%u", \ + (unsigned int) __tid); \ + __set_vma_name (__stack, __stacksize, __stack_name); \ + }) + +/* Add or remove an associated name to the PD VMA stack. */ +static void +name_stack_maps (struct pthread *pd, bool set) +{ +#if _STACK_GROWS_DOWN && !defined(NEED_SEPARATE_REGISTER_STACK) + void *stack = pd->stackblock + pd->guardsize; +#else + void *stack = pd->stackblock; +#endif + size_t stacksize = pd->stackblock_size - pd->guardsize; + + if (!set) + __set_vma_name (stack, stacksize, NULL); + else + { + unsigned int tid = pd->tid; + if (pd->user_stack) + SET_STACK_NAME (" glibc: pthread user stack: ", stack, stacksize, tid); + else + SET_STACK_NAME (" glibc: pthread stack: ", stack, stacksize, tid); + } +} diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index 6a41d50109..63cb684f04 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -369,6 +369,9 @@ start_thread (void *arg) /* Initialize pointers to locale data. */ __ctype_init (); + /* Name the thread stack if kernel supports it. */ + name_stack_maps (pd, true); + /* Register rseq TLS to the kernel. */ { bool do_rseq = THREAD_GETMEM (pd, flags) & ATTR_FLAG_DO_RSEQ; @@ -571,6 +574,9 @@ start_thread (void *arg) /* Free the TCB. */ __nptl_free_tcb (pd); + /* Remove the associated name from the thread stack. */ + name_stack_maps (pd, false); + out: /* We cannot call '_exit' here. '_exit' will terminate the process.