public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 0/7] Add a tunable to decorate anonymous memory maps
@ 2023-10-28 19:55 Adhemerval Zanella
  2023-10-28 19:55 ` [PATCH v2 1/7] linux: Add PR_SET_VMA_ANON_NAME support Adhemerval Zanella
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: Adhemerval Zanella @ 2023-10-28 19:55 UTC (permalink / raw)
  To: libc-alpha, Ian Rogers, Francesco Nigro, Carlos O'Donell,
	Siddhesh Poyarekar

Linux 4.5 removed thread stack annotations due to the complexity of
computing them, and Linux 5.17 added support to naming anonymous virtual
memory areas through the prctl syscall [1].

Android and other projects like sanitizers uses this feature to improve
debugability and a way to user understand better what kind of memory
runtime allocates.

The patchset adds annotations for the pthread stack, on both glibc
created and user-provided, on loader minimal malloc and on malloc arenas
and default allocation. For instance, on x86_64 the resulting mapping of
the newly tst-decorate-maps shows:

5649d25bd000-5649d25bf000 r--p 00000000 103:05 40141614                  <buildir>/elf/tst-decorate-maps
5649d25bf000-5649d25c3000 r-xp 00002000 103:05 40141614                  <buildir>/elf/tst-decorate-maps
5649d25c3000-5649d25c5000 r--p 00006000 103:05 40141614                  <buildir>/elf/tst-decorate-maps
5649d25c5000-5649d25c6000 r--p 00007000 103:05 40141614                  <buildir>/elf/tst-decorate-maps
5649d25c6000-5649d25c7000 rw-p 00008000 103:05 40141614                  <buildir>/elf/tst-decorate-maps
5649d36c4000-5649d36e5000 rw-p 00000000 00:00 0                          [heap]
7fc76c000000-7fc76c021000 rw-p 00000000 00:00 0                          [anon: glibc: malloc arena]
7fc76c021000-7fc770000000 ---p 00000000 00:00 0
7fc774000000-7fc774021000 rw-p 00000000 00:00 0                          [anon: glibc: malloc arena]
7fc774021000-7fc778000000 ---p 00000000 00:00 0
7fc77c000000-7fc77c021000 rw-p 00000000 00:00 0                          [anon: glibc: malloc arena]
7fc77c021000-7fc780000000 ---p 00000000 00:00 0
7fc784000000-7fc784021000 rw-p 00000000 00:00 0                          [anon: glibc: malloc arena]
7fc784021000-7fc788000000 ---p 00000000 00:00 0
7fc788000000-7fc788021000 rw-p 00000000 00:00 0                          [anon: glibc: malloc arena]
7fc788021000-7fc78c000000 ---p 00000000 00:00 0
7fc78c000000-7fc78c021000 rw-p 00000000 00:00 0                          [anon: glibc: malloc arena]
7fc78c021000-7fc790000000 ---p 00000000 00:00 0
7fc790000000-7fc790021000 rw-p 00000000 00:00 0                          [anon: glibc: malloc arena]
7fc790021000-7fc794000000 ---p 00000000 00:00 0
7fc796800000-7fc797000000 rw-p 00000000 00:00 0                          [anon: glibc: pthread stack: 2188506]
7fc797000000-7fc797800000 rw-p 00000000 00:00 0                          [anon: glibc: pthread stack: 2188505]
7fc797800000-7fc798000000 rw-p 00000000 00:00 0                          [anon: glibc: pthread stack: 2188504]
7fc798000000-7fc798800000 rw-p 00000000 00:00 0                          [anon: glibc: pthread stack: 2188503]
7fc798800000-7fc799000000 rw-p 00000000 00:00 0                          [anon: glibc: pthread stack: 2188502]
7fc799000000-7fc799800000 rw-p 00000000 00:00 0                          [anon: glibc: pthread stack: 2188501]
7fc799800000-7fc79a000000 rw-p 00000000 00:00 0                          [anon: glibc: pthread stack: 2188500]
7fc79a000000-7fc79a800000 rw-p 00000000 00:00 0                          [anon: glibc: pthread stack: 2188499]
7fc79a800000-7fc79a826000 r--p 00000000 103:05 38343761                  <buildir>/libc.so
7fc79a826000-7fc79a99a000 r-xp 00026000 103:05 38343761                  <buildir>/libc.so
7fc79a99a000-7fc79a9f1000 r--p 0019a000 103:05 38343761                  <buildir>/libc.so
7fc79a9f1000-7fc79a9f5000 r--p 001f0000 103:05 38343761                  <buildir>/libc.so
7fc79a9f5000-7fc79a9f7000 rw-p 001f4000 103:05 38343761                  <buildir>/libc.so
7fc79a9f7000-7fc79aa04000 rw-p 00000000 00:00 0
7fc79aabb000-7fc79aafb000 rw-p 00000000 00:00 0                          [anon: glibc: pthread user stack: 2188508]
7fc79aafb000-7fc79ab3b000 rw-p 00000000 00:00 0                          [anon: glibc: pthread user stack: 2188507]
7fc79ab3b000-7fc79ab7c000 rw-p 00000000 00:00 0                          [anon: glibc: malloc]
7fc79ab7c000-7fc79ab7d000 rw-s 00000000 00:01 19458                      /dev/zero (deleted)
7fc79ab7d000-7fc79ab82000 rw-p 00000000 00:00 0                          [anon: glibc: loader malloc]
7fc79ab82000-7fc79ab83000 r--p 00000000 103:05 40141609                  <buildir>/elf/ld.so
7fc79ab83000-7fc79aba9000 r-xp 00001000 103:05 40141609                  <buildir>/elf/ld.so
7fc79aba9000-7fc79abb3000 r--p 00027000 103:05 40141609                  <buildir>/elf/ld.so
7fc79abb3000-7fc79abb5000 r--p 00031000 103:05 40141609                  <buildir>/elf/ld.so
7fc79abb5000-7fc79abb7000 rw-p 00033000 103:05 40141609                  <buildir>/elf/ld.so
7ffdb2f1d000-7ffdb2f3f000 rw-p 00000000 00:00 0                          [stack]
7ffdb2f7a000-7ffdb2f7e000 r--p 00000000 00:00 0                          [vvar]
7ffdb2f7e000-7ffdb2f80000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

The PR_SET_VMA_ANON_NAME support is currently only enabled through a
configurable kernel switch, mainly because assigning a name to a
anonymous virtual memory area might prevent that area from being
merged with adjacent virtual memory areas. There is also a potential
scalability issue, where the prctl requires take the mmap global lock
and it still not fully fixed in Linux [1] (for pthread stacks and
arenas, it is mitigated by the stack cached and the arena reuse).

So the decoration is only enable through a new tunable,
glibc.mem.decorate_maps.

[1] https://github.com/torvalds/linux/commit/65376df582174ffcec9e6471bf5b0dd79ba05e4a
[1] https://github.com/torvalds/linux/commit/9a10064f5625d5572c3626c1516e0bebc6c9fe9b

Changes from v1:
* Fixed arm thumb build.
* Added decoration on assert and __libc_fatal.

Adhemerval Zanella (7):
  linux: Add PR_SET_VMA_ANON_NAME support
  support: Add support_set_vma_name
  nptl: Decorate thread stack on pthread_create
  malloc: Decorate malloc maps
  assert: Decorate error message buffer
  linux: Decorate __libc_fatal error buffer
  elf: Add glibc.mem.decorate_maps tunable

 NEWS                                 |   5 +
 assert/assert.c                      |   2 +
 elf/Makefile                         |   7 +
 elf/dl-minimal-malloc.c              |   2 +
 elf/dl-tunables.list                 |   5 +
 elf/tst-decorate-maps.c              | 197 +++++++++++++++++++++++++++
 include/sys/prctl.h                  |   5 +
 malloc/arena.c                       |   4 +
 malloc/malloc.c                      |   5 +
 manual/tunables.texi                 |  12 ++
 nptl/Makefile                        |   4 +
 nptl/allocatestack.c                 |  40 ++++++
 nptl/pthread_create.c                |   6 +
 support/Makefile                     |   1 +
 support/support.h                    |   4 +
 support/support_set_vma_name.c       |  49 +++++++
 sysdeps/generic/setvmaname.h         |  27 ++++
 sysdeps/posix/libc_fatal.c           |   3 +
 sysdeps/unix/sysv/linux/Makefile     |   1 +
 sysdeps/unix/sysv/linux/setvmaname.c |  48 +++++++
 sysdeps/unix/sysv/linux/setvmaname.h |  36 +++++
 21 files changed, 463 insertions(+)
 create mode 100644 elf/tst-decorate-maps.c
 create mode 100644 support/support_set_vma_name.c
 create mode 100644 sysdeps/generic/setvmaname.h
 create mode 100644 sysdeps/unix/sysv/linux/setvmaname.c
 create mode 100644 sysdeps/unix/sysv/linux/setvmaname.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 1/7] linux: Add PR_SET_VMA_ANON_NAME support
  2023-10-28 19:55 [PATCH v2 0/7] Add a tunable to decorate anonymous memory maps Adhemerval Zanella
@ 2023-10-28 19:55 ` Adhemerval Zanella
  2023-10-31 20:03   ` DJ Delorie
  2023-10-28 19:55 ` [PATCH v2 2/7] support: Add support_set_vma_name Adhemerval Zanella
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2023-10-28 19:55 UTC (permalink / raw)
  To: libc-alpha, Ian Rogers, Francesco Nigro, Carlos O'Donell,
	Siddhesh Poyarekar

Linux 5.17 added support to naming anonymous virtual memory areas
through the prctl syscall.  The __set_vma_name is a wrapper to avoid
optimizing the prctl call if the kernel does not support it.

If the kernel does not support PR_SET_VMA_ANON_NAME, prctl returns
EINVAL. And it also returns the same error for an invalid argument.
Since it is an internal-only API, it assumes well-formatted input:
aligned START, with (START, START+LEN) being a valid memory range,
and NAME with a limit of 80 characters without an invalid one
("\\`$[]").
---
 include/sys/prctl.h                  |  5 ++++
 sysdeps/generic/setvmaname.h         | 27 +++++++++++++++++
 sysdeps/unix/sysv/linux/Makefile     |  1 +
 sysdeps/unix/sysv/linux/setvmaname.c | 44 ++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/setvmaname.h | 36 +++++++++++++++++++++++
 5 files changed, 113 insertions(+)
 create mode 100644 sysdeps/generic/setvmaname.h
 create mode 100644 sysdeps/unix/sysv/linux/setvmaname.c
 create mode 100644 sysdeps/unix/sysv/linux/setvmaname.h

diff --git a/include/sys/prctl.h b/include/sys/prctl.h
index d33f3a290e..8e8e05b07c 100644
--- a/include/sys/prctl.h
+++ b/include/sys/prctl.h
@@ -3,6 +3,11 @@
 
 # ifndef _ISOMAC
 
+#  ifndef PR_SET_VMA
+#   define PR_SET_VMA            0x53564d41
+#   define PR_SET_VMA_ANON_NAME  0
+#  endif
+
 extern int __prctl (int __option, ...);
 libc_hidden_proto (__prctl)
 
diff --git a/sysdeps/generic/setvmaname.h b/sysdeps/generic/setvmaname.h
new file mode 100644
index 0000000000..2824587e9f
--- /dev/null
+++ b/sysdeps/generic/setvmaname.h
@@ -0,0 +1,27 @@
+/* Utilities functions to name memory mappings.
+   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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef __SETVMANAME_H
+#define __SETVMANAME_H
+
+static inline
+void __set_vma_name (void *start, size_t len, const char *name)
+{
+}
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 063719bae6..250df6f455 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -97,6 +97,7 @@ sysdep_routines += \
   readahead \
   setfsgid \
   setfsuid \
+  setvmaname \
   signalfd \
   splice \
   sysctl \
diff --git a/sysdeps/unix/sysv/linux/setvmaname.c b/sysdeps/unix/sysv/linux/setvmaname.c
new file mode 100644
index 0000000000..9960ab5917
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/setvmaname.c
@@ -0,0 +1,44 @@
+/* Utilities functions to name memory mappings.
+   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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <ldsodefs.h>
+#include <setvmaname.h>
+#include <sys/prctl.h>
+#include <sysdep.h>
+
+/* If PR_SET_VMA_ANON_NAME is not supported by the kernel, prctl returns
+   EINVAL.  However, it also returns the same error for invalid argument.
+   Since it is an internal-only API, it assumes well formatted input:
+   aligned START, with (START, START+LEN) being a valid memory range,
+   and NAME with a limit of 80 characters without invalid one ("\\`$[]").  */
+
+void
+__set_vma_name (void *start, size_t len, const char *name)
+{
+  static int prctl_supported = 1;
+  if (atomic_load_relaxed (&prctl_supported) == 0)
+    return;
+
+  int r = INTERNAL_SYSCALL_CALL (prctl, PR_SET_VMA, PR_SET_VMA_ANON_NAME,
+				 start, len, name);
+  if (r == 0 || r != -EINVAL)
+    return;
+
+  atomic_store_relaxed (&prctl_supported, 0);
+  return;
+}
diff --git a/sysdeps/unix/sysv/linux/setvmaname.h b/sysdeps/unix/sysv/linux/setvmaname.h
new file mode 100644
index 0000000000..eaa7a7a32e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/setvmaname.h
@@ -0,0 +1,36 @@
+/* Utilities functions to name memory mappings.
+   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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef __SETVMANAME_H
+#define __SETVMANAME_H
+
+/* Set the NAME to the anonymous memory map START with size of LEN.
+   It assumes well-formatted input.  */
+#if IS_IN(libc) || IS_IN(rtld)
+void __set_vma_name (void *start, size_t len, const char *name)
+  attribute_hidden;
+#else
+#include <sys/prctl.h>
+
+static inline void __set_vma_name (void *start, size_t len, const char *name)
+{
+  prctl (PR_SET_VMA, PR_SET_VMA_ANON_NAME, start, len, name);
+}
+#endif
+
+#endif
-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 2/7] support: Add support_set_vma_name
  2023-10-28 19:55 [PATCH v2 0/7] Add a tunable to decorate anonymous memory maps Adhemerval Zanella
  2023-10-28 19:55 ` [PATCH v2 1/7] linux: Add PR_SET_VMA_ANON_NAME support Adhemerval Zanella
@ 2023-10-28 19:55 ` Adhemerval Zanella
  2023-10-31 21:34   ` DJ Delorie
  2023-10-28 19:55 ` [PATCH v2 3/7] nptl: Decorate thread stack on pthread_create Adhemerval Zanella
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2023-10-28 19:55 UTC (permalink / raw)
  To: libc-alpha, Ian Rogers, Francesco Nigro, Carlos O'Donell,
	Siddhesh Poyarekar

Check if kernel supports prctl (PR_SET_VMA, PR_SET_VMA_ANON_NAME, ...).
---
 support/Makefile               |  1 +
 support/support.h              |  4 +++
 support/support_set_vma_name.c | 49 ++++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+)
 create mode 100644 support/support_set_vma_name.c

diff --git a/support/Makefile b/support/Makefile
index 917a858bd1..54a8cc30ac 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -80,6 +80,7 @@ libsupport-routines = \
   support_select_modifies_timeout \
   support_select_normalizes_timeout \
   support_set_small_thread_stack_size \
+  support_set_vma_name \
   support_shared_allocate \
   support_small_stack_thread_attribute \
   support_socket_so_timestamp_time64 \
diff --git a/support/support.h b/support/support.h
index b7f76bf080..659ef25b06 100644
--- a/support/support.h
+++ b/support/support.h
@@ -235,6 +235,10 @@ void support_stack_free (struct support_stack *stack);
    The returned value is the lowest file descriptor number.  */
 int support_open_dev_null_range (int num, int flags, mode_t mode);
 
+
+/* Check if kernel supports set VMA range name.  */
+extern bool support_set_vma_name (void);
+
 __END_DECLS
 
 #endif /* SUPPORT_H */
diff --git a/support/support_set_vma_name.c b/support/support_set_vma_name.c
new file mode 100644
index 0000000000..41f5dea409
--- /dev/null
+++ b/support/support_set_vma_name.c
@@ -0,0 +1,49 @@
+/* Check if kernel supports set VMA range name.
+   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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+#include <sys/mman.h>
+#ifdef __linux__
+# include <sys/prctl.h>
+#endif
+
+bool
+support_set_vma_name (void)
+{
+#ifdef __linux__
+  size_t size = sysconf (_SC_PAGESIZE);
+  if (size == -1)
+    FAIL_EXIT1 ("sysconf (_SC_PAGESIZE): %m\n");
+
+  void *vma = xmmap (0,
+		     size,
+		     PROT_NONE,
+		     MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
+		     -1);
+
+  int r = prctl (PR_SET_VMA, PR_SET_VMA_ANON_NAME, vma, size, "vmaname");
+
+  xmunmap (vma, size);
+
+  return r == 0;
+#else
+  return false;
+#endif
+}
-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 3/7] nptl: Decorate thread stack on pthread_create
  2023-10-28 19:55 [PATCH v2 0/7] Add a tunable to decorate anonymous memory maps Adhemerval Zanella
  2023-10-28 19:55 ` [PATCH v2 1/7] linux: Add PR_SET_VMA_ANON_NAME support Adhemerval Zanella
  2023-10-28 19:55 ` [PATCH v2 2/7] support: Add support_set_vma_name Adhemerval Zanella
@ 2023-10-28 19:55 ` Adhemerval Zanella
  2023-11-01  2:04   ` DJ Delorie
  2023-10-28 19:55 ` [PATCH v2 4/7] malloc: Decorate malloc maps Adhemerval Zanella
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2023-10-28 19:55 UTC (permalink / raw)
  To: libc-alpha, Ian Rogers, Francesco Nigro, Carlos O'Donell,
	Siddhesh Poyarekar

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: <tid>]

And for user-provided stacks:

  [anon: glibc: pthread user stack: <tid>]

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 <irogers@google.com>

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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+#include <support/xstdio.h>
+#include <support/xthread.h>
+#include <support/xunistd.h>
+#include <sys/mman.h>
+
+#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 <support/test-driver.c>
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 <nptl-stack.h>
 #include <libc-lock.h>
 #include <tls-internal.h>
+#include <intprops.h>
+#include <setvmaname.h>
 
 /* 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.
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 4/7] malloc: Decorate malloc maps
  2023-10-28 19:55 [PATCH v2 0/7] Add a tunable to decorate anonymous memory maps Adhemerval Zanella
                   ` (2 preceding siblings ...)
  2023-10-28 19:55 ` [PATCH v2 3/7] nptl: Decorate thread stack on pthread_create Adhemerval Zanella
@ 2023-10-28 19:55 ` Adhemerval Zanella
  2023-11-01  2:28   ` DJ Delorie
  2023-10-28 19:55 ` [PATCH v2 5/7] assert: Decorate error message buffer Adhemerval Zanella
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2023-10-28 19:55 UTC (permalink / raw)
  To: libc-alpha, Ian Rogers, Francesco Nigro, Carlos O'Donell,
	Siddhesh Poyarekar

Add anonymous mmap annotations on loader malloc, malloc when it
allocates memory with mmap, and on malloc arena.  The /proc/self/maps
will now print:

   [anon: glibc: malloc arena]
   [anon: glibc: malloc]
   [anon: glibc: loader malloc]

On arena allocation, glibc annotates only the read/write mapping.

Checked on x86_64-linux-gnu and aarch64-linux-gnu.
---
 elf/Makefile            |  4 ++++
 elf/dl-minimal-malloc.c |  2 ++
 elf/tst-decorate-maps.c | 37 +++++++++++++++++++++++++++++++++++++
 malloc/arena.c          |  4 ++++
 malloc/malloc.c         |  5 +++++
 nptl/Makefile           |  4 ++++
 6 files changed, 56 insertions(+)

diff --git a/elf/Makefile b/elf/Makefile
index a82590703c..c3cf63a443 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -3021,3 +3021,7 @@ $(objpfx)tst-dlclose-lazy.out: \
   $(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so
 
 $(objpfx)tst-decorate-maps: $(shared-thread-library)
+
+tst-decorate-maps-ENV = \
+  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
+tst-decorate-maps-ARGS = 8
diff --git a/elf/dl-minimal-malloc.c b/elf/dl-minimal-malloc.c
index 27549645d0..da36986269 100644
--- a/elf/dl-minimal-malloc.c
+++ b/elf/dl-minimal-malloc.c
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <ldsodefs.h>
 #include <malloc/malloc-internal.h>
+#include <setvmaname.h>
 
 static void *alloc_ptr, *alloc_end, *alloc_last_block;
 
@@ -60,6 +61,7 @@ __minimal_malloc (size_t n)
 		     MAP_ANON|MAP_PRIVATE, -1, 0);
       if (page == MAP_FAILED)
 	return NULL;
+      __set_vma_name (page, nup, " glibc: loader malloc");
       if (page != alloc_end)
 	alloc_ptr = page;
       alloc_end = page + nup;
diff --git a/elf/tst-decorate-maps.c b/elf/tst-decorate-maps.c
index bbb7972094..bf508489c4 100644
--- a/elf/tst-decorate-maps.c
+++ b/elf/tst-decorate-maps.c
@@ -32,15 +32,22 @@
 
 static pthread_barrier_t b;
 
+static int expected_n_arenas;
+
 static void *
 tf (void *closure)
 {
+  void *p = xmalloc (1024);
+
   /* 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);
 
+  free (p);
+
   return NULL;
 }
 
@@ -48,6 +55,9 @@ struct proc_maps_t
 {
   int n_def_threads;
   int n_user_threads;
+  int n_arenas;
+  int n_malloc_mmap;
+  int n_loader_malloc_mmap;
 };
 
 static struct proc_maps_t
@@ -69,6 +79,12 @@ read_proc_maps (void)
 	r.n_def_threads++;
       else if (strstr (line, "[anon: glibc: pthread user stack:") != NULL)
 	r.n_user_threads++;
+      else if (strstr (line, "[anon: glibc: malloc arena]") != NULL)
+	r.n_arenas++;
+      else if (strstr (line, "[anon: glibc: malloc]") != NULL)
+	r.n_malloc_mmap++;
+      else if (strstr (line, "[anon: glibc: loader malloc]") != NULL)
+	r.n_loader_malloc_mmap++;
     }
   free (line);
   xfclose (f);
@@ -90,6 +106,9 @@ do_test_threads (bool set_guard)
 
   xpthread_barrier_init (&b, NULL, num_threads + 1);
 
+  /* Issue a large malloc to trigger a mmap call.  */
+  void *p = xmalloc (256 * 1024);
+
   pthread_t thr[num_threads];
   {
     int i = 0;
@@ -128,6 +147,10 @@ do_test_threads (bool set_guard)
     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);
+    TEST_COMPARE (r.n_arenas, expected_n_arenas);
+    TEST_COMPARE (r.n_malloc_mmap, 1);
+    /* On some architectures the loader might use more than one page.  */
+    TEST_VERIFY (r.n_loader_malloc_mmap >= 1);
   }
 
   /* Let the threads finish.  */
@@ -140,8 +163,22 @@ do_test_threads (bool set_guard)
     struct proc_maps_t r = read_proc_maps ();
     TEST_COMPARE (r.n_def_threads, 0);
     TEST_COMPARE (r.n_user_threads, 0);
+    TEST_COMPARE (r.n_arenas, expected_n_arenas);
+    TEST_COMPARE (r.n_malloc_mmap, 1);
+    TEST_VERIFY (r.n_loader_malloc_mmap >= 1);
   }
+
+  free (p);
+}
+
+static void
+do_prepare (int argc, char *argv[])
+{
+  TEST_VERIFY_EXIT (argc == 2);
+  expected_n_arenas = strtol (argv[1], NULL, 10);
+  expected_n_arenas = expected_n_arenas - 1;
 }
+#define PREPARE do_prepare
 
 static int
 do_test (void)
diff --git a/malloc/arena.c b/malloc/arena.c
index 6f03955ff2..d1e214ac2e 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -17,6 +17,7 @@
    not, see <https://www.gnu.org/licenses/>.  */
 
 #include <stdbool.h>
+#include <setvmaname.h>
 
 #define TUNABLE_NAMESPACE malloc
 #include <elf/dl-tunables.h>
@@ -436,6 +437,9 @@ alloc_new_heap  (size_t size, size_t top_pad, size_t pagesize,
       return 0;
     }
 
+  /* Only considere the actual usable range.  */
+  __set_vma_name (p2, size, " glibc: malloc arena");
+
   madvise_thp (p2, size);
 
   h = (heap_info *) p2;
diff --git a/malloc/malloc.c b/malloc/malloc.c
index d0bbbf3710..78a531bc7a 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -218,6 +218,7 @@
 #include <sys/sysinfo.h>
 
 #include <ldsodefs.h>
+#include <setvmaname.h>
 
 #include <unistd.h>
 #include <stdio.h>    /* needed for malloc_stats */
@@ -2428,6 +2429,8 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
     madvise_thp (mm, size);
 #endif
 
+  __set_vma_name (mm, size, " glibc: malloc");
+
   /*
     The offset to the start of the mmapped region is stored in the prev_size
     field of the chunk.  This allows us to adjust returned start address to
@@ -2513,6 +2516,8 @@ sysmalloc_mmap_fallback (long int *s, INTERNAL_SIZE_T nb,
     madvise_thp (mbrk, size);
 #endif
 
+  __set_vma_name (mbrk, size, " glibc: malloc");
+
   /* Record that we no longer have a contiguous sbrk region.  After the first
      time mmap is used as backup, we do not ever rely on contiguous space
      since this could incorrectly bridge regions.  */
diff --git a/nptl/Makefile b/nptl/Makefile
index ffa5722e48..d969419af7 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -699,6 +699,10 @@ tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so
 tst-setuid1-static-ENV = \
   LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)elf:$(common-objpfx)nss
 
+tst-pthread-proc-maps-ENV = \
+  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
+tst-pthread-proc-maps-ARGS = 8
+
 # The tests here better do not run in parallel.
 ifeq ($(run-built-tests),yes)
 ifneq ($(filter %tests,$(MAKECMDGOALS)),)
-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 5/7] assert: Decorate error message buffer
  2023-10-28 19:55 [PATCH v2 0/7] Add a tunable to decorate anonymous memory maps Adhemerval Zanella
                   ` (3 preceding siblings ...)
  2023-10-28 19:55 ` [PATCH v2 4/7] malloc: Decorate malloc maps Adhemerval Zanella
@ 2023-10-28 19:55 ` Adhemerval Zanella
  2023-11-01  2:31   ` DJ Delorie
  2023-10-28 19:55 ` [PATCH v2 6/7] linux: Decorate __libc_fatal error buffer Adhemerval Zanella
  2023-10-28 19:55 ` [PATCH v2 7/7] elf: Add glibc.mem.decorate_maps tunable Adhemerval Zanella
  6 siblings, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2023-10-28 19:55 UTC (permalink / raw)
  To: libc-alpha, Ian Rogers, Francesco Nigro, Carlos O'Donell,
	Siddhesh Poyarekar

---
 assert/assert.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/assert/assert.c b/assert/assert.c
index b7c7a4a1ba..bf0f4a69f5 100644
--- a/assert/assert.c
+++ b/assert/assert.c
@@ -24,6 +24,7 @@
 #include <sysdep.h>
 #include <unistd.h>
 #include <sys/mman.h>
+#include <setvmaname.h>
 
 
 extern const char *__progname;
@@ -71,6 +72,7 @@ __assert_fail_base (const char *fmt, const char *assertion, const char *file,
 	{
 	  buf->size = total;
 	  strcpy (buf->msg, str);
+	  __set_vma_name (buf, total, " glibc: assert");
 
 	  /* We have to free the old buffer since the application might
 	     catch the SIGABRT signal.  */
-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 6/7] linux: Decorate __libc_fatal error buffer
  2023-10-28 19:55 [PATCH v2 0/7] Add a tunable to decorate anonymous memory maps Adhemerval Zanella
                   ` (4 preceding siblings ...)
  2023-10-28 19:55 ` [PATCH v2 5/7] assert: Decorate error message buffer Adhemerval Zanella
@ 2023-10-28 19:55 ` Adhemerval Zanella
  2023-11-01  2:32   ` DJ Delorie
  2023-10-28 19:55 ` [PATCH v2 7/7] elf: Add glibc.mem.decorate_maps tunable Adhemerval Zanella
  6 siblings, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2023-10-28 19:55 UTC (permalink / raw)
  To: libc-alpha, Ian Rogers, Francesco Nigro, Carlos O'Donell,
	Siddhesh Poyarekar

---
 sysdeps/posix/libc_fatal.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c
index cf28387ee6..f564d232bf 100644
--- a/sysdeps/posix/libc_fatal.c
+++ b/sysdeps/posix/libc_fatal.c
@@ -31,6 +31,7 @@
 #include <sys/mman.h>
 #include <sys/uio.h>
 #include <not-cancel.h>
+#include <setvmaname.h>
 
 #ifdef FATAL_PREPARE_INCLUDE
 #include FATAL_PREPARE_INCLUDE
@@ -116,6 +117,8 @@ __libc_message_impl (const char *fmt, ...)
 	    wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
 	  *wp = '\0';
 
+	  __set_vma_name (buf, total, " glibc: fatal");
+
 	  /* We have to free the old buffer since the application might
 	     catch the SIGABRT signal.  */
 	  struct abort_msg_s *old = atomic_exchange_acquire (&__abort_msg,
-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 7/7] elf: Add glibc.mem.decorate_maps tunable
  2023-10-28 19:55 [PATCH v2 0/7] Add a tunable to decorate anonymous memory maps Adhemerval Zanella
                   ` (5 preceding siblings ...)
  2023-10-28 19:55 ` [PATCH v2 6/7] linux: Decorate __libc_fatal error buffer Adhemerval Zanella
@ 2023-10-28 19:55 ` Adhemerval Zanella
  2023-11-01  3:09   ` DJ Delorie
  6 siblings, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2023-10-28 19:55 UTC (permalink / raw)
  To: libc-alpha, Ian Rogers, Francesco Nigro, Carlos O'Donell,
	Siddhesh Poyarekar

The PR_SET_VMA_ANON_NAME support is only enabled through a configurable
kernel switch, mainly because assigning a name to a
anonymous virtual memory area might prevent that area from being
merged with adjacent virtual memory areas.

For instance, with the following code:

   void *p1 = mmap (NULL,
                    1024 * 4096,
                    PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS,
                    -1,
                    0);

   void *p2 = mmap (p1 + (1024 * 4096),
                    1024 * 4096,
                    PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS,
                    -1,
                    0);

The kernel will potentially merge both mappings resulting in only one
segment of size 0x800000.  If the segment is names with
PR_SET_VMA_ANON_NAME with different names, it results in two mappings.

Although this will unlikely be an issue for pthread stacks and malloc
arenas (since for pthread stacks the guard page will result in
a PROT_NONE segment, similar to the alignment requirement for the arena
block), it still might prevent the mmap memory allocated for detail
malloc.

There is also another potential scalability issue, where the prctl
requires
to take the mmap global lock which is still not fully fixed in Linux
[1] (for pthread stacks and arenas, it is mitigated by the stack
cached and the arena reuse).

So this patch disables anonymous mapping annotations as default and
add a new tunable, glibc.mem.decorate_maps, can be used to enable
it.

[1] https://lwn.net/Articles/906852/

Checked on x86_64-linux-gnu and aarch64-linux-gnu.
---
 NEWS                                 |  5 +++++
 elf/Makefile                         |  2 +-
 elf/dl-tunables.list                 |  5 +++++
 manual/tunables.texi                 | 12 ++++++++++++
 sysdeps/unix/sysv/linux/setvmaname.c |  4 ++++
 5 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index 9432564444..67f6e63b14 100644
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,11 @@ Major new features:
   and the wfN format length modifiers for arguments pointing to types
   int_fastN_t or uint_fastN_t, as specified in draft ISO C2X.
 
+* A new tunable, glibc.mem.decorate_maps, can be used to add additional
+  information on underlying memory allocated by the glibc (for instance,
+  on thread stack created by pthread_create or memory allocated by
+  malloc).
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * The ldconfig program now skips file names containing ';' or ending in
diff --git a/elf/Makefile b/elf/Makefile
index c3cf63a443..2603b90961 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -3023,5 +3023,5 @@ $(objpfx)tst-dlclose-lazy.out: \
 $(objpfx)tst-decorate-maps: $(shared-thread-library)
 
 tst-decorate-maps-ENV = \
-  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
+  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024:glibc.mem.decorate_maps=1
 tst-decorate-maps-ARGS = 8
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
index 695ba7192e..888d2ede04 100644
--- a/elf/dl-tunables.list
+++ b/elf/dl-tunables.list
@@ -160,6 +160,11 @@ glibc {
       maxval: 255
       security_level: SXID_IGNORE
     }
+    decorate_maps {
+      type: INT_32
+      minval: 0
+      maxval: 1
+    }
   }
 
   rtld {
diff --git a/manual/tunables.texi b/manual/tunables.texi
index 776fd93fd9..2a5ad73e9d 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -653,6 +653,18 @@ support in the kernel if this tunable has any non-zero value.
 The default value is @samp{0}, which disables all memory tagging.
 @end deftp
 
+@deftp Tunable glibc.mem.decorate_maps
+If the kernel supports naming anonymous virtual memory areas (since
+Linux version 5.17), this tunable can be used to control whether
+@theglibc{} decorates the underlying memory obtained from operating
+system with a string describing its usage (for instance, on the thread
+stack created by @code{ptthread_create} or memory allocated by
+@code{malloc}).
+
+This tunable takes a value of 0 and 1, where 1 enables the feature.
+The default value is @samp{0}, which disables the decoration.
+@end deftp
+
 @node gmon Tunables
 @section gmon Tunables
 @cindex gmon tunables
diff --git a/sysdeps/unix/sysv/linux/setvmaname.c b/sysdeps/unix/sysv/linux/setvmaname.c
index 9960ab5917..62237fcf7c 100644
--- a/sysdeps/unix/sysv/linux/setvmaname.c
+++ b/sysdeps/unix/sysv/linux/setvmaname.c
@@ -20,6 +20,7 @@
 #include <setvmaname.h>
 #include <sys/prctl.h>
 #include <sysdep.h>
+#include <elf/dl-tunables.h>
 
 /* If PR_SET_VMA_ANON_NAME is not supported by the kernel, prctl returns
    EINVAL.  However, it also returns the same error for invalid argument.
@@ -30,6 +31,9 @@
 void
 __set_vma_name (void *start, size_t len, const char *name)
 {
+  if (TUNABLE_GET (glibc, mem, decorate_maps, int32_t, NULL) == 0)
+    return;
+
   static int prctl_supported = 1;
   if (atomic_load_relaxed (&prctl_supported) == 0)
     return;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 1/7] linux: Add PR_SET_VMA_ANON_NAME support
  2023-10-28 19:55 ` [PATCH v2 1/7] linux: Add PR_SET_VMA_ANON_NAME support Adhemerval Zanella
@ 2023-10-31 20:03   ` DJ Delorie
  0 siblings, 0 replies; 17+ messages in thread
From: DJ Delorie @ 2023-10-31 20:03 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha


LGTM
Reviewed-by: DJ Delorie <dj@redhat.com>

Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
> diff --git a/include/sys/prctl.h b/include/sys/prctl.h
>  
>  # ifndef _ISOMAC
>  
> +#  ifndef PR_SET_VMA
> +#   define PR_SET_VMA            0x53564d41
> +#   define PR_SET_VMA_ANON_NAME  0
> +#  endif
> +

These match the kernel includes on rawhide, so OK.

> diff --git a/sysdeps/generic/setvmaname.h b/sysdeps/generic/setvmaname.h
> new file mode 100644
> index 0000000000..2824587e9f
> --- /dev/null
> +++ b/sysdeps/generic/setvmaname.h
> @@ -0,0 +1,27 @@
> +/* Utilities functions to name memory mappings.
> +   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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef __SETVMANAME_H
> +#define __SETVMANAME_H
> +
> +static inline
> +void __set_vma_name (void *start, size_t len, const char *name)
> +{
> +}
> +
> +#endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 063719bae6..250df6f455 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -97,6 +97,7 @@ sysdep_routines += \
>    readahead \
>    setfsgid \
>    setfsuid \
> +  setvmaname \
>    signalfd \
>    splice \
>    sysctl \

Ok.

> diff --git a/sysdeps/unix/sysv/linux/setvmaname.c b/sysdeps/unix/sysv/linux/setvmaname.c
> new file mode 100644
> index 0000000000..9960ab5917
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/setvmaname.c
> @@ -0,0 +1,44 @@
> +/* Utilities functions to name memory mappings.
> +   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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <ldsodefs.h>
> +#include <setvmaname.h>
> +#include <sys/prctl.h>
> +#include <sysdep.h>

Ok.

> +/* If PR_SET_VMA_ANON_NAME is not supported by the kernel, prctl returns
> +   EINVAL.  However, it also returns the same error for invalid argument.
> +   Since it is an internal-only API, it assumes well formatted input:
> +   aligned START, with (START, START+LEN) being a valid memory range,
> +   and NAME with a limit of 80 characters without invalid one ("\\`$[]").  */
> +
> +void
> +__set_vma_name (void *start, size_t len, const char *name)
> +{
> +  static int prctl_supported = 1;
> +  if (atomic_load_relaxed (&prctl_supported) == 0)
> +    return;
> +
> +  int r = INTERNAL_SYSCALL_CALL (prctl, PR_SET_VMA, PR_SET_VMA_ANON_NAME,
> +				 start, len, name);
> +  if (r == 0 || r != -EINVAL)
> +    return;

I'll point out that this logic is redundant, but I like that it conveys
more meaning this way :-)

Ok.

> +  atomic_store_relaxed (&prctl_supported, 0);
> +  return;
> +}

Ok.

> diff --git a/sysdeps/unix/sysv/linux/setvmaname.h b/sysdeps/unix/sysv/linux/setvmaname.h
> new file mode 100644
> index 0000000000..eaa7a7a32e
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/setvmaname.h
> @@ -0,0 +1,36 @@
> +/* Utilities functions to name memory mappings.
> +   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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef __SETVMANAME_H
> +#define __SETVMANAME_H
> +
> +/* Set the NAME to the anonymous memory map START with size of LEN.
> +   It assumes well-formatted input.  */
> +#if IS_IN(libc) || IS_IN(rtld)
> +void __set_vma_name (void *start, size_t len, const char *name)
> +  attribute_hidden;
> +#else
> +#include <sys/prctl.h>
> +
> +static inline void __set_vma_name (void *start, size_t len, const char *name)
> +{
> +  prctl (PR_SET_VMA, PR_SET_VMA_ANON_NAME, start, len, name);
> +}
> +#endif
> +
> +#endif

Ok.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 2/7] support: Add support_set_vma_name
  2023-10-28 19:55 ` [PATCH v2 2/7] support: Add support_set_vma_name Adhemerval Zanella
@ 2023-10-31 21:34   ` DJ Delorie
  2023-11-01 11:58     ` Adhemerval Zanella Netto
  0 siblings, 1 reply; 17+ messages in thread
From: DJ Delorie @ 2023-10-31 21:34 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha


Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
> diff --git a/support/support.h b/support/support.h
> index b7f76bf080..659ef25b06 100644
> --- a/support/support.h
> +++ b/support/support.h
> @@ -235,6 +235,10 @@ void support_stack_free (struct support_stack *stack);
>     The returned value is the lowest file descriptor number.  */
>  int support_open_dev_null_range (int num, int flags, mode_t mode);
>  
> +
> +/* Check if kernel supports set VMA range name.  */
> +extern bool support_set_vma_name (void);
> +
>  __END_DECLS
>  
>  #endif /* SUPPORT_H */

This doesn't match the idiom the rest of the support_*() functions use;
I would expect this to mean "support's version of set_vma_name()" and
would expect it to set the vma name.

Something like "support_set_vma_name_supported ()" would (sadly) be more
appropriate.

> diff --git a/support/support_set_vma_name.c b/support/support_set_vma_name.c
> new file mode 100644
> index 0000000000..41f5dea409
> --- /dev/null
> +++ b/support/support_set_vma_name.c
> @@ -0,0 +1,49 @@
> +/* Check if kernel supports set VMA range name.
> +   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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <support/xunistd.h>
> +#include <sys/mman.h>
> +#ifdef __linux__
> +# include <sys/prctl.h>
> +#endif
> +
> +bool
> +support_set_vma_name (void)
> +{
> +#ifdef __linux__
> +  size_t size = sysconf (_SC_PAGESIZE);
> +  if (size == -1)
> +    FAIL_EXIT1 ("sysconf (_SC_PAGESIZE): %m\n");
> +
> +  void *vma = xmmap (0,
> +		     size,
> +		     PROT_NONE,
> +		     MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
> +		     -1);
> +
> +  int r = prctl (PR_SET_VMA, PR_SET_VMA_ANON_NAME, vma, size, "vmaname");
> +
> +  xmunmap (vma, size);
> +
> +  return r == 0;
> +#else
> +  return false;
> +#endif
> +}

Ok.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 3/7] nptl: Decorate thread stack on pthread_create
  2023-10-28 19:55 ` [PATCH v2 3/7] nptl: Decorate thread stack on pthread_create Adhemerval Zanella
@ 2023-11-01  2:04   ` DJ Delorie
  0 siblings, 0 replies; 17+ messages in thread
From: DJ Delorie @ 2023-11-01  2:04 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha


One spelling fix.
One question but doesn't block

LGTM.
Reviewed-by: DJ Delorie <dj@redhat.com>

Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:

> diff --git a/elf/Makefile b/elf/Makefile
> +  tst-decorate-maps \

Ok.

> +
> +$(objpfx)tst-decorate-maps: $(shared-thread-library)

Ok.

> diff --git a/elf/tst-decorate-maps.c b/elf/tst-decorate-maps.c
> +/* 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <support/test-driver.h>
> +#include <support/xstdio.h>
> +#include <support/xthread.h>
> +#include <support/xunistd.h>
> +#include <sys/mman.h>

Ok.

> +#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.  */

Spelling: "mapping"

> +  xpthread_barrier_wait (&b);
> +
> +  return NULL;
> +}

Ok.

> +struct proc_maps_t
> +{
> +  int n_def_threads;
> +  int n_user_threads;
> +};

Ok.

> +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 };

Misleading, but OK.  Should be { 0, 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;
> +}

Ok.

> +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,
> +    };

10 threads total, ok.

> +  xpthread_barrier_init (&b, NULL, num_threads + 1);

Ok.

> +  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);
> +      }

Ok.

> +    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);
> +      }
> +  }

Ok.

> +  /* 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);
> +  }

Ok.

> +  /* 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);
> +  }
> +}

Ok.

> +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 <support/test-driver.c>

Ok.

> diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
> +#include <intprops.h>
> +#include <setvmaname.h>

Ok.

> +/* 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);		\
> +   })

Ok.

> +/* 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;

Do we have any stack-grows-up systems to test this on?

> +#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);
> +    }
> +}

Ok.

> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
>    /* Initialize pointers to locale data.  */
>    __ctype_init ();
>  
> +  /* Name the thread stack if kernel supports it.  */
> +  name_stack_maps (pd, true);
> +

Ok.

> @@ -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.

Ok.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 4/7] malloc: Decorate malloc maps
  2023-10-28 19:55 ` [PATCH v2 4/7] malloc: Decorate malloc maps Adhemerval Zanella
@ 2023-11-01  2:28   ` DJ Delorie
  0 siblings, 0 replies; 17+ messages in thread
From: DJ Delorie @ 2023-11-01  2:28 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha


LGTM
Reviewed-by: DJ Delorie <dj@redhat.com>

Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
> Add anonymous mmap annotations on loader malloc, malloc when it
> allocates memory with mmap, and on malloc arena.  The /proc/self/maps
> will now print:
>
>    [anon: glibc: malloc arena]
>    [anon: glibc: malloc]
>    [anon: glibc: loader malloc]
>
> On arena allocation, glibc annotates only the read/write mapping.
>
> Checked on x86_64-linux-gnu and aarch64-linux-gnu.
> ---
>  elf/Makefile            |  4 ++++
>  elf/dl-minimal-malloc.c |  2 ++
>  elf/tst-decorate-maps.c | 37 +++++++++++++++++++++++++++++++++++++
>  malloc/arena.c          |  4 ++++
>  malloc/malloc.c         |  5 +++++
>  nptl/Makefile           |  4 ++++
>  6 files changed, 56 insertions(+)


> diff --git a/elf/Makefile b/elf/Makefile
> +
> +tst-decorate-maps-ENV = \
> +  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
> +tst-decorate-maps-ARGS = 8

Ok.

> diff --git a/elf/dl-minimal-malloc.c b/elf/dl-minimal-malloc.c
> +#include <setvmaname.h>

Ok.

>  		     MAP_ANON|MAP_PRIVATE, -1, 0);
>        if (page == MAP_FAILED)
>  	return NULL;
> +      __set_vma_name (page, nup, " glibc: loader malloc");
>        if (page != alloc_end)
>  	alloc_ptr = page;
>        alloc_end = page + nup;

Ok.

> diff --git a/elf/tst-decorate-maps.c b/elf/tst-decorate-maps.c
>  
> +static int expected_n_arenas;
> +
>  static void *
>  tf (void *closure)
>  {
> +  void *p = xmalloc (1024);
> +
>    /* 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);
>  
> +  free (p);
> +
>    return NULL;
>  }

Ok.  Enough to create an arena, not enough to mmap the chunk.

> @@ -48,6 +55,9 @@ struct proc_maps_t
>  {
>    int n_def_threads;
>    int n_user_threads;
> +  int n_arenas;
> +  int n_malloc_mmap;
> +  int n_loader_malloc_mmap;
>  };

Ok.

> @@ -69,6 +79,12 @@ read_proc_maps (void)
>  	r.n_def_threads++;
>        else if (strstr (line, "[anon: glibc: pthread user stack:") != NULL)
>  	r.n_user_threads++;
> +      else if (strstr (line, "[anon: glibc: malloc arena]") != NULL)
> +	r.n_arenas++;
> +      else if (strstr (line, "[anon: glibc: malloc]") != NULL)
> +	r.n_malloc_mmap++;
> +      else if (strstr (line, "[anon: glibc: loader malloc]") != NULL)
> +	r.n_loader_malloc_mmap++;
>      }
>    free (line);
>    xfclose (f);

Ok.

> @@ -90,6 +106,9 @@ do_test_threads (bool set_guard)
>  
>    xpthread_barrier_init (&b, NULL, num_threads + 1);
>  
> +  /* Issue a large malloc to trigger a mmap call.  */
> +  void *p = xmalloc (256 * 1024);
> +
>    pthread_t thr[num_threads];
>    {
>      int i = 0;

Ok.

> @@ -128,6 +147,10 @@ do_test_threads (bool set_guard)
>      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);
> +    TEST_COMPARE (r.n_arenas, expected_n_arenas);
> +    TEST_COMPARE (r.n_malloc_mmap, 1);
> +    /* On some architectures the loader might use more than one page.  */
> +    TEST_VERIFY (r.n_loader_malloc_mmap >= 1);
>    }

Ok.

>    /* Let the threads finish.  */
> @@ -140,8 +163,22 @@ do_test_threads (bool set_guard)
>      struct proc_maps_t r = read_proc_maps ();
>      TEST_COMPARE (r.n_def_threads, 0);
>      TEST_COMPARE (r.n_user_threads, 0);
> +    TEST_COMPARE (r.n_arenas, expected_n_arenas);
> +    TEST_COMPARE (r.n_malloc_mmap, 1);
> +    TEST_VERIFY (r.n_loader_malloc_mmap >= 1);
>    }
> +
> +  free (p);
> +}

Ok.

> +static void
> +do_prepare (int argc, char *argv[])
> +{
> +  TEST_VERIFY_EXIT (argc == 2);
> +  expected_n_arenas = strtol (argv[1], NULL, 10);
> +  expected_n_arenas = expected_n_arenas - 1;
>  }
> +#define PREPARE do_prepare

Ok.

> diff --git a/malloc/arena.c b/malloc/arena.c
> index 6f03955ff2..d1e214ac2e 100644
> --- a/malloc/arena.c
> +++ b/malloc/arena.c
> @@ -17,6 +17,7 @@
>     not, see <https://www.gnu.org/licenses/>.  */
>  
>  #include <stdbool.h>
> +#include <setvmaname.h>

Ok.

>  #define TUNABLE_NAMESPACE malloc
>  #include <elf/dl-tunables.h>
> @@ -436,6 +437,9 @@ alloc_new_heap  (size_t size, size_t top_pad, size_t pagesize,
>        return 0;
>      }
>  
> +  /* Only considere the actual usable range.  */
> +  __set_vma_name (p2, size, " glibc: malloc arena");
> +
>    madvise_thp (p2, size);
>  

Ok.

> diff --git a/malloc/malloc.c b/malloc/malloc.c
>  #include <sys/sysinfo.h>
>  
>  #include <ldsodefs.h>
> +#include <setvmaname.h>

Ok.

> @@ -2428,6 +2429,8 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
>      madvise_thp (mm, size);
>  #endif
>  
> +  __set_vma_name (mm, size, " glibc: malloc");
> +

Ok.

> @@ -2513,6 +2516,8 @@ sysmalloc_mmap_fallback (long int *s, INTERNAL_SIZE_T nb,
>      madvise_thp (mbrk, size);
>  #endif
>  
> +  __set_vma_name (mbrk, size, " glibc: malloc");
> +

Ok.

> diff --git a/nptl/Makefile b/nptl/Makefile
> +tst-pthread-proc-maps-ENV = \
> +  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
> +tst-pthread-proc-maps-ARGS = 8
> +

Ok.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 5/7] assert: Decorate error message buffer
  2023-10-28 19:55 ` [PATCH v2 5/7] assert: Decorate error message buffer Adhemerval Zanella
@ 2023-11-01  2:31   ` DJ Delorie
  0 siblings, 0 replies; 17+ messages in thread
From: DJ Delorie @ 2023-11-01  2:31 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha


LGTM
Reviewed-by: DJ Delorie <dj@redhat.com>

Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
> diff --git a/assert/assert.c b/assert/assert.c
> index b7c7a4a1ba..bf0f4a69f5 100644
> --- a/assert/assert.c
> +++ b/assert/assert.c
> @@ -24,6 +24,7 @@
>  #include <sysdep.h>
>  #include <unistd.h>
>  #include <sys/mman.h>
> +#include <setvmaname.h>
>  
>  
>  extern const char *__progname;
> @@ -71,6 +72,7 @@ __assert_fail_base (const char *fmt, const char *assertion, const char *file,
>  	{
>  	  buf->size = total;
>  	  strcpy (buf->msg, str);
> +	  __set_vma_name (buf, total, " glibc: assert");
>  
>  	  /* We have to free the old buffer since the application might
>  	     catch the SIGABRT signal.  */

Ok.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 6/7] linux: Decorate __libc_fatal error buffer
  2023-10-28 19:55 ` [PATCH v2 6/7] linux: Decorate __libc_fatal error buffer Adhemerval Zanella
@ 2023-11-01  2:32   ` DJ Delorie
  0 siblings, 0 replies; 17+ messages in thread
From: DJ Delorie @ 2023-11-01  2:32 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha


LGTM
Reviewed-by: DJ Delorie <dj@redhat.com>

Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
> diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c
> index cf28387ee6..f564d232bf 100644
> --- a/sysdeps/posix/libc_fatal.c
> +++ b/sysdeps/posix/libc_fatal.c
> @@ -31,6 +31,7 @@
>  #include <sys/mman.h>
>  #include <sys/uio.h>
>  #include <not-cancel.h>
> +#include <setvmaname.h>
>  
>  #ifdef FATAL_PREPARE_INCLUDE
>  #include FATAL_PREPARE_INCLUDE
> @@ -116,6 +117,8 @@ __libc_message_impl (const char *fmt, ...)
>  	    wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
>  	  *wp = '\0';
>  
> +	  __set_vma_name (buf, total, " glibc: fatal");
> +
>  	  /* We have to free the old buffer since the application might
>  	     catch the SIGABRT signal.  */
>  	  struct abort_msg_s *old = atomic_exchange_acquire (&__abort_msg,

Ok.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 7/7] elf: Add glibc.mem.decorate_maps tunable
  2023-10-28 19:55 ` [PATCH v2 7/7] elf: Add glibc.mem.decorate_maps tunable Adhemerval Zanella
@ 2023-11-01  3:09   ` DJ Delorie
  2023-11-01 12:53     ` Adhemerval Zanella Netto
  0 siblings, 1 reply; 17+ messages in thread
From: DJ Delorie @ 2023-11-01  3:09 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha


LGTM with a few optional suggestions
Reviewed-by: DJ Delorie <dj@redhat.com>

Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
> diff --git a/NEWS b/NEWS
> index 9432564444..67f6e63b14 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -38,6 +38,11 @@ Major new features:
>    and the wfN format length modifiers for arguments pointing to types
>    int_fastN_t or uint_fastN_t, as specified in draft ISO C2X.
>  
> +* A new tunable, glibc.mem.decorate_maps, can be used to add additional
> +  information on underlying memory allocated by the glibc (for instance,
> +  on thread stack created by pthread_create or memory allocated by
> +  malloc).
> +

Ok.  Could mention /proc/*/maps

> diff --git a/elf/Makefile b/elf/Makefile
> index c3cf63a443..2603b90961 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -3023,5 +3023,5 @@ $(objpfx)tst-dlclose-lazy.out: \
>  $(objpfx)tst-decorate-maps: $(shared-thread-library)
>  
>  tst-decorate-maps-ENV = \
> -  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
> +  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024:glibc.mem.decorate_maps=1
>  tst-decorate-maps-ARGS = 8

Ok.

> diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
> index 695ba7192e..888d2ede04 100644
> --- a/elf/dl-tunables.list
> +++ b/elf/dl-tunables.list
> @@ -160,6 +160,11 @@ glibc {
>        maxval: 255
>        security_level: SXID_IGNORE
>      }
> +    decorate_maps {
> +      type: INT_32
> +      minval: 0
> +      maxval: 1
> +    }
>    }

Ok.

> diff --git a/manual/tunables.texi b/manual/tunables.texi
> index 776fd93fd9..2a5ad73e9d 100644
> --- a/manual/tunables.texi
> +++ b/manual/tunables.texi
> @@ -653,6 +653,18 @@ support in the kernel if this tunable has any non-zero value.
>  The default value is @samp{0}, which disables all memory tagging.
>  @end deftp
>  
> +@deftp Tunable glibc.mem.decorate_maps
> +If the kernel supports naming anonymous virtual memory areas (since
> +Linux version 5.17), this tunable can be used to control whether
> +@theglibc{} decorates the underlying memory obtained from operating
> +system with a string describing its usage (for instance, on the thread
> +stack created by @code{ptthread_create} or memory allocated by
> +@code{malloc}).
> +
> +This tunable takes a value of 0 and 1, where 1 enables the feature.
> +The default value is @samp{0}, which disables the decoration.
> +@end deftp
> +

Ok.  Again, could mention /proc/*/maps.  Could mention that the kernel
might be built without such support by choice, too.

> diff --git a/sysdeps/unix/sysv/linux/setvmaname.c b/sysdeps/unix/sysv/linux/setvmaname.c
> index 9960ab5917..62237fcf7c 100644
> --- a/sysdeps/unix/sysv/linux/setvmaname.c
> +++ b/sysdeps/unix/sysv/linux/setvmaname.c
> @@ -20,6 +20,7 @@
>  #include <setvmaname.h>
>  #include <sys/prctl.h>
>  #include <sysdep.h>
> +#include <elf/dl-tunables.h>
>  
>  /* If PR_SET_VMA_ANON_NAME is not supported by the kernel, prctl returns
>     EINVAL.  However, it also returns the same error for invalid argument.
> @@ -30,6 +31,9 @@
>  void
>  __set_vma_name (void *start, size_t len, const char *name)
>  {
> +  if (TUNABLE_GET (glibc, mem, decorate_maps, int32_t, NULL) == 0)
> +    return;
> +
>    static int prctl_supported = 1;
>    if (atomic_load_relaxed (&prctl_supported) == 0)
>      return;

Ok, but would be better to check the tunable after the prctl_supported
flag (and set the flag) to avoid calling __tunable_get_val for every
call.  Unless the intention was to allow changing the tunable during
runtime, in which case, ignore this comment ;-)


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 2/7] support: Add support_set_vma_name
  2023-10-31 21:34   ` DJ Delorie
@ 2023-11-01 11:58     ` Adhemerval Zanella Netto
  0 siblings, 0 replies; 17+ messages in thread
From: Adhemerval Zanella Netto @ 2023-11-01 11:58 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libc-alpha



On 31/10/23 18:34, DJ Delorie wrote:
> 
> Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
>> diff --git a/support/support.h b/support/support.h
>> index b7f76bf080..659ef25b06 100644
>> --- a/support/support.h
>> +++ b/support/support.h
>> @@ -235,6 +235,10 @@ void support_stack_free (struct support_stack *stack);
>>     The returned value is the lowest file descriptor number.  */
>>  int support_open_dev_null_range (int num, int flags, mode_t mode);
>>  
>> +
>> +/* Check if kernel supports set VMA range name.  */
>> +extern bool support_set_vma_name (void);
>> +
>>  __END_DECLS
>>  
>>  #endif /* SUPPORT_H */
> 
> This doesn't match the idiom the rest of the support_*() functions use;
> I would expect this to mean "support's version of set_vma_name()" and
> would expect it to set the vma name.
> 
> Something like "support_set_vma_name_supported ()" would (sadly) be more
> appropriate.

Ack, I will change it.

> 
>> diff --git a/support/support_set_vma_name.c b/support/support_set_vma_name.c
>> new file mode 100644
>> index 0000000000..41f5dea409
>> --- /dev/null
>> +++ b/support/support_set_vma_name.c
>> @@ -0,0 +1,49 @@
>> +/* Check if kernel supports set VMA range name.
>> +   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
>> +   <https://www.gnu.org/licenses/>.  */
>> +
>> +#include <support/check.h>
>> +#include <support/support.h>
>> +#include <support/xunistd.h>
>> +#include <sys/mman.h>
>> +#ifdef __linux__
>> +# include <sys/prctl.h>
>> +#endif
>> +
>> +bool
>> +support_set_vma_name (void)
>> +{
>> +#ifdef __linux__
>> +  size_t size = sysconf (_SC_PAGESIZE);
>> +  if (size == -1)
>> +    FAIL_EXIT1 ("sysconf (_SC_PAGESIZE): %m\n");
>> +
>> +  void *vma = xmmap (0,
>> +		     size,
>> +		     PROT_NONE,
>> +		     MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
>> +		     -1);
>> +
>> +  int r = prctl (PR_SET_VMA, PR_SET_VMA_ANON_NAME, vma, size, "vmaname");
>> +
>> +  xmunmap (vma, size);
>> +
>> +  return r == 0;
>> +#else
>> +  return false;
>> +#endif
>> +}
> 
> Ok.
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 7/7] elf: Add glibc.mem.decorate_maps tunable
  2023-11-01  3:09   ` DJ Delorie
@ 2023-11-01 12:53     ` Adhemerval Zanella Netto
  0 siblings, 0 replies; 17+ messages in thread
From: Adhemerval Zanella Netto @ 2023-11-01 12:53 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libc-alpha



On 01/11/23 00:09, DJ Delorie wrote:
> 
> LGTM with a few optional suggestions
> Reviewed-by: DJ Delorie <dj@redhat.com>
> 
> Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
>> diff --git a/NEWS b/NEWS
>> index 9432564444..67f6e63b14 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -38,6 +38,11 @@ Major new features:
>>    and the wfN format length modifiers for arguments pointing to types
>>    int_fastN_t or uint_fastN_t, as specified in draft ISO C2X.
>>  
>> +* A new tunable, glibc.mem.decorate_maps, can be used to add additional
>> +  information on underlying memory allocated by the glibc (for instance,
>> +  on thread stack created by pthread_create or memory allocated by
>> +  malloc).
>> +
> 
> Ok.  Could mention /proc/*/maps
> 
>> diff --git a/elf/Makefile b/elf/Makefile
>> index c3cf63a443..2603b90961 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -3023,5 +3023,5 @@ $(objpfx)tst-dlclose-lazy.out: \
>>  $(objpfx)tst-decorate-maps: $(shared-thread-library)
>>  
>>  tst-decorate-maps-ENV = \
>> -  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024
>> +  GLIBC_TUNABLES=glibc.malloc.arena_max=8:glibc.malloc.mmap_threshold=1024:glibc.mem.decorate_maps=1
>>  tst-decorate-maps-ARGS = 8
> 
> Ok.
> 
>> diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
>> index 695ba7192e..888d2ede04 100644
>> --- a/elf/dl-tunables.list
>> +++ b/elf/dl-tunables.list
>> @@ -160,6 +160,11 @@ glibc {
>>        maxval: 255
>>        security_level: SXID_IGNORE
>>      }
>> +    decorate_maps {
>> +      type: INT_32
>> +      minval: 0
>> +      maxval: 1
>> +    }
>>    }
> 
> Ok.
> 
>> diff --git a/manual/tunables.texi b/manual/tunables.texi
>> index 776fd93fd9..2a5ad73e9d 100644
>> --- a/manual/tunables.texi
>> +++ b/manual/tunables.texi
>> @@ -653,6 +653,18 @@ support in the kernel if this tunable has any non-zero value.
>>  The default value is @samp{0}, which disables all memory tagging.
>>  @end deftp
>>  
>> +@deftp Tunable glibc.mem.decorate_maps
>> +If the kernel supports naming anonymous virtual memory areas (since
>> +Linux version 5.17), this tunable can be used to control whether
>> +@theglibc{} decorates the underlying memory obtained from operating
>> +system with a string describing its usage (for instance, on the thread
>> +stack created by @code{ptthread_create} or memory allocated by
>> +@code{malloc}).
>> +
>> +This tunable takes a value of 0 and 1, where 1 enables the feature.
>> +The default value is @samp{0}, which disables the decoration.
>> +@end deftp
>> +
> 
> Ok.  Again, could mention /proc/*/maps.  Could mention that the kernel
> might be built without such support by choice, too.

Ack, I will extend it.

> 
>> diff --git a/sysdeps/unix/sysv/linux/setvmaname.c b/sysdeps/unix/sysv/linux/setvmaname.c
>> index 9960ab5917..62237fcf7c 100644
>> --- a/sysdeps/unix/sysv/linux/setvmaname.c
>> +++ b/sysdeps/unix/sysv/linux/setvmaname.c
>> @@ -20,6 +20,7 @@
>>  #include <setvmaname.h>
>>  #include <sys/prctl.h>
>>  #include <sysdep.h>
>> +#include <elf/dl-tunables.h>
>>  
>>  /* If PR_SET_VMA_ANON_NAME is not supported by the kernel, prctl returns
>>     EINVAL.  However, it also returns the same error for invalid argument.
>> @@ -30,6 +31,9 @@
>>  void
>>  __set_vma_name (void *start, size_t len, const char *name)
>>  {
>> +  if (TUNABLE_GET (glibc, mem, decorate_maps, int32_t, NULL) == 0)
>> +    return;
>> +
>>    static int prctl_supported = 1;
>>    if (atomic_load_relaxed (&prctl_supported) == 0)
>>      return;
> 
> Ok, but would be better to check the tunable after the prctl_supported
> flag (and set the flag) to avoid calling __tunable_get_val for every
> call.  Unless the intention was to allow changing the tunable during
> runtime, in which case, ignore this comment ;-)
> 

Indeed you are right, we don't have the tunable runtime support and I am
not sure if adding this would make sense for this tunable.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2023-11-01 12:53 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-28 19:55 [PATCH v2 0/7] Add a tunable to decorate anonymous memory maps Adhemerval Zanella
2023-10-28 19:55 ` [PATCH v2 1/7] linux: Add PR_SET_VMA_ANON_NAME support Adhemerval Zanella
2023-10-31 20:03   ` DJ Delorie
2023-10-28 19:55 ` [PATCH v2 2/7] support: Add support_set_vma_name Adhemerval Zanella
2023-10-31 21:34   ` DJ Delorie
2023-11-01 11:58     ` Adhemerval Zanella Netto
2023-10-28 19:55 ` [PATCH v2 3/7] nptl: Decorate thread stack on pthread_create Adhemerval Zanella
2023-11-01  2:04   ` DJ Delorie
2023-10-28 19:55 ` [PATCH v2 4/7] malloc: Decorate malloc maps Adhemerval Zanella
2023-11-01  2:28   ` DJ Delorie
2023-10-28 19:55 ` [PATCH v2 5/7] assert: Decorate error message buffer Adhemerval Zanella
2023-11-01  2:31   ` DJ Delorie
2023-10-28 19:55 ` [PATCH v2 6/7] linux: Decorate __libc_fatal error buffer Adhemerval Zanella
2023-11-01  2:32   ` DJ Delorie
2023-10-28 19:55 ` [PATCH v2 7/7] elf: Add glibc.mem.decorate_maps tunable Adhemerval Zanella
2023-11-01  3:09   ` DJ Delorie
2023-11-01 12:53     ` Adhemerval Zanella Netto

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).