From patchwork Thu Oct 26 17:11:42 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: 738334 Delivered-To: patch@linaro.org Received: by 2002:ab3:1905:0:b0:23f:8cfb:5ad7 with SMTP id u5csp1312139ltc; Thu, 26 Oct 2023 10:12:56 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHst8HDu+KAHokwQnTHWm2dnq5FVNNzqX7C6elXP3tPV8dQBSMGxyXZK/GNacKC+ROXWszL X-Received: by 2002:a05:6214:3007:b0:653:5bed:83d4 with SMTP id ke7-20020a056214300700b006535bed83d4mr295007qvb.30.1698340376629; Thu, 26 Oct 2023 10:12:56 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1698340376; cv=pass; d=google.com; s=arc-20160816; b=JMkOBq82cAzJL0V6XA2kTMQCh3iU5wOTo5I9rPP3/76bWcrXbkm7WOfS6Y2kAnPNrT XU36OzeMdQ4HSALM7GIwYLqAYJZ48UTgsu6tc+9ud+nTg7koKCnIiZsFjpwKQQfigmnO QlFx5dHfrFvImCXaDrc0bLurrMZGnoVQxKwhd5AUXw/hsNXZCFBq4iSoDEZjt75EjHW+ nkFMtc7bbwBx4DhCGr/LeAd4ATzOqqmwBnYdYIYfs5ITo3zJ9yLbKFnbDIhcaU5/AE0/ IVkBYLNXahhtqWnstMI3DzOSA3V0G88xMsGKkWIuWSid61dmtKKmR8Y/H526Fv/ItBVM iYIw== 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=o5gvjmIAhmQEblp7hcqVh/EYlFZy+7DIVZ5HyCCsRrUCyTSEgiqGTPLX8yILso/2pc kGcx1ZBFptN2b3O1kJGKEdwCK87GDCV2wJoHve8XGjacvew8IzQ8zP/T2yHGNbXwTbje dZ41bTLPIJnbDPV65/0J6ZFRNRbVfETQOFdavLN7twy41huCiBHgeenhkFbCvY09y3B7 UfRbfk29CIq3iZZ3YFuveqm2wCHCeEtT73GZeQDSwXbmrm/jm8wT7JLPQieFXxrAm74e NIOECNNhZBPMXo4dFoTNs7WzyS5XXZnbEZ4ueFqnGqyjA59i/7sbCj6RNZmEpzi9OizR /o9w== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dWxUlOH8; 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 oh8-20020a056214438800b0066cee934ae4si10101810qvb.229.2023.10.26.10.12.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 10:12:56 -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=dWxUlOH8; 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 1165E3858025 for ; Thu, 26 Oct 2023 17:12:56 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) by sourceware.org (Postfix) with ESMTPS id 5D1CD385C414 for ; Thu, 26 Oct 2023 17:11:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5D1CD385C414 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 5D1CD385C414 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::42e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698340321; cv=none; b=LYPQTIiFKxJARiqfWa5UoCiF52YpODoJqdEObaNabYlx9YI1fq0AXhn7vTSnC023TjIuOZ7tLalIk/QCpoIDrCyXJjZnQJXS2F5tqu1rq/gZY7feoQS4CVTRM5iBtvRJ6NjxHEGstKHUBYEj5oxfu/cisN7Mi64F6aKs/u9/rBc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698340321; c=relaxed/simple; bh=l8vV3WJkYT21asT5LcSedDaKdeFb/WqwQuwiByv2tBI=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=O2rda0eV+zpx3xEpE4O2HRmXAGnpGMhkKha5v72Xk9mo5kLjNbG1aWvGMTJFnHD7R8EEU+2q+b2JGTl13isRlfzUWlDusG9vzhx4MYS0a9hKgAXsANtcsljAublQtlSvjUm4C6ByWTDjEhsRUszoJ31lTLAZk2uhLk6j7Xpgj3s= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x42e.google.com with SMTP id d2e1a72fcca58-6b87c1edfd5so1101627b3a.1 for ; Thu, 26 Oct 2023 10:11:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698340318; x=1698945118; 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=dWxUlOH8U5rm7CGtFoRVuIseFZnQ5kah/ku74HjHEGuqFmNphLFD8uDiqJe21cTvDE Av+vGlhUX1PP+dMIPF8aUTw9dTjQAn0Ht+FUe0CUWZ/GWCaGTqOdxH7FVSWIviAEzzXN gARV51W7maTdpchDjoTr6w9gVVmbJZ/cxmM0NRw18Or8TL9MNFGhR1H98O7K6QTopln+ l60fwEObeSf4YE/GXddpSHcZFc+xsnxmY1BhmpsDw/4PdLC1+J7i2fsrhnvXIvGVGeTK uR3MQskPXpbJZl1KjnJZqe+a+03eQJDudWr+skDO4nB7kZNw/SN+n6aVJqm6lXYg3upa ignQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698340318; x=1698945118; 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=Vg/2XM637ZHP7fibollindXqYXjAijagRXYyKrNCSO+bNixpj0sfVRJpOCgVPpFGD9 zQDNzR5g0BdlC5If8L6fKHSg0wJBWtX7rzFmKcPCgVsAKfncGOdLsvpOPIQcIFIQO9Fs e7T0xLctJLWKHmeVRsMQSxoOZnWLXO+8+OB5B3A24UkP92n1pIJEjsr1oQWXttmcylKb Tksq7bXrLvqCiCDIQ3oFVRXBz51ymOfEdQVC1m7YFFUp8nq0t9auTGGxPkJF9vhD86HS mnkxyD6w9qsxk7EY3hsplb/FLg6jbgpa5vRx/787k1aKMA7FgxkPd1krRSCt0kmbxmgY T17Q== X-Gm-Message-State: AOJu0YwsFg7i6JQKVH3smLOXrFyuA6zOdEkrkTBuFmMQyCmfoaj37gFT ocTCcSV3GXFyc0jBh0cD+ZlQluAm0RnyTU5ncFbLdQ== X-Received: by 2002:a05:6a20:4406:b0:153:a461:d96e with SMTP id ce6-20020a056a20440600b00153a461d96emr507938pzb.47.1698340317868; Thu, 26 Oct 2023 10:11:57 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c3:a647:ad90:6e37:bd13:fb33]) by smtp.gmail.com with ESMTPSA id w18-20020aa78592000000b006bee5ad4efasm11516394pfn.67.2023.10.26.10.11.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 10:11:57 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org, Ian Rogers , Francesco Nigro , Carlos O'Donell , Siddhesh Poyarekar Subject: [PATCH 3/5] nptl: Decorate thread stack on pthread_create Date: Thu, 26 Oct 2023 14:11:42 -0300 Message-Id: <20231026171144.2188549-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231026171144.2188549-1-adhemerval.zanella@linaro.org> References: <20231026171144.2188549-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.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 --- 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.