about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-11-01 09:56:11 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-11-07 10:27:57 -0300
commitbf033c0072554366fe9617c283c982594059ad9d (patch)
tree73b5e76afbfe2aadcfaad86a424b5c770040bb8c /sysdeps
parentf10ba2ab250b04e47868cfb888df22058436173d (diff)
downloadglibc-bf033c0072554366fe9617c283c982594059ad9d.tar.gz
glibc-bf033c0072554366fe9617c283c982594059ad9d.tar.xz
glibc-bf033c0072554366fe9617c283c982594059ad9d.zip
elf: Add glibc.mem.decorate_maps tunable
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.
Reviewed-by: DJ Delorie <dj@redhat.com>
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/unix/sysv/linux/setvmaname.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/sysdeps/unix/sysv/linux/setvmaname.c b/sysdeps/unix/sysv/linux/setvmaname.c
index 9960ab5917..cd6d571772 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.
@@ -34,11 +35,15 @@ __set_vma_name (void *start, size_t len, const char *name)
   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;
-
+  /* Set the prctl as not supported to avoid checking the tunable on every
+     call.  */
+  if (TUNABLE_GET (glibc, mem, decorate_maps, int32_t, NULL) != 0)
+    {
+      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;
 }