support: add support_ptr_after_free
Checks
| Context |
Check |
Description |
| redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
| redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
Commit Message
Some tests use pointers after the associated memory has been freed.
On targets that support memory tagging, using such pointers even
for test purposes might be impossible. To work around this, we add
new function that would allow to clear a pointer in a target-specific
way.
We modify 3 relevant malloc tests: tst-malloc-backtrace, tst-tcfree3,
and tst-safe-linking.
---
malloc/tst-malloc-backtrace.c | 6 ++-
malloc/tst-memalign-2.c | 2 +-
malloc/tst-memalign-3.c | 2 +-
malloc/tst-realloc.c | 2 +-
malloc/tst-safe-linking.c | 6 ++-
malloc/tst-tcfree3.c | 6 +++
support/{address-diff.h => test-pointer.h} | 12 ++++--
sysdeps/aarch64/Makefile | 1 +
sysdeps/aarch64/support-address-diff.c | 2 +-
sysdeps/aarch64/support-use-after-free.c | 47 ++++++++++++++++++++++
sysdeps/generic/Makefile | 1 +
sysdeps/generic/support-address-diff.c | 2 +-
sysdeps/generic/support-use-after-free.c | 24 +++++++++++
13 files changed, 102 insertions(+), 11 deletions(-)
rename support/{address-diff.h => test-pointer.h} (77%)
create mode 100644 sysdeps/aarch64/support-use-after-free.c
create mode 100644 sysdeps/generic/support-use-after-free.c
Comments
On Mai 06 2026, Yury Khrustalev wrote:
> diff --git a/sysdeps/aarch64/support-use-after-free.c b/sysdeps/aarch64/support-use-after-free.c
> new file mode 100644
> index 0000000000..eff5ff7c9a
> --- /dev/null
> +++ b/sysdeps/aarch64/support-use-after-free.c
> @@ -0,0 +1,47 @@
> +/* Support functions testing malloc: aarch64 version.
> + Copyright (C) 2026 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 "test-pointer.h"
> +
> +#include <sys/ifunc.h>
> +#include <sys/auxv.h>
> +
> +/* This version clears bits 59:56 (4 bits) to remove possible
> + MTE tag from the pointer without trying to access memory
> + that this pointer points to. */
> +static void *ptr_after_free_mte (void *ptr)
> +{
> + return (void *)((uintptr_t)ptr & ~(0xfull << 56ull));
> +}
> +
> +static void *ptr_after_free_generic (void *ptr)
> +{
> + return ptr;
> +}
> +
> +static void * __attribute__ ((unused))
> +ptr_after_free_resolver (unsigned long a0, const unsigned long *a1)
> +{
> + unsigned long hwcap2 = __ifunc_hwcap (_IFUNC_ARG_AT_HWCAP2, a0, a1);
> + if (hwcap2 & HWCAP2_MTE)
> + return (void *)ptr_after_free_mte;
> + return (void *)ptr_after_free_generic;
> +}
> +
> +void *support_ptr_after_free (void *ptr)
> +__attribute__ ((ifunc ("ptr_after_free_resolver")));
> \ No newline at end of file
Please add the newline.
Hi Yury,
> Some tests use pointers after the associated memory has been freed.
> On targets that support memory tagging, using such pointers even
> for test purposes might be impossible. To work around this, we add
> new function that would allow to clear a pointer in a target-specific
> way.
OK with the newline fixed as Andreas pointed out.
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
Cheers,
Wilco
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <support/support.h>
+#include <support/test-pointer.h>
#include <libc-diag.h>
#include "tst-malloc-aux.h"
@@ -37,7 +38,10 @@ call_free (void *ptr)
by a prior call to free(). */
DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free");
#endif
- *(size_t *)(ptr - sizeof (size_t)) = 1;
+ /* We attempt to write to the chunk header thus corrupting memory.
+ If memory tagging is used, we need to make sure that tag in ptr
+ is cleared. */
+ *(size_t *)(support_ptr_after_free (ptr) - sizeof (size_t)) = 1;
#if __GNUC_PREREQ (12, 0)
DIAG_POP_NEEDS_COMMENT;
#endif
@@ -23,7 +23,7 @@
#include <unistd.h>
#include <array_length.h>
#include <libc-pointer-arith.h>
-#include <support/address-diff.h>
+#include <support/test-pointer.h>
#include <support/check.h>
#include "tst-malloc-aux.h"
@@ -24,7 +24,7 @@
#include <unistd.h>
#include <array_length.h>
#include <libc-pointer-arith.h>
-#include <support/address-diff.h>
+#include <support/test-pointer.h>
#include <support/check.h>
#include <support/xthread.h>
#include "tst-malloc-aux.h"
@@ -22,7 +22,7 @@
#include <string.h>
#include <libc-diag.h>
#include <support/check.h>
-#include <support/address-diff.h>
+#include <support/test-pointer.h>
#include "tst-malloc-aux.h"
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
+#include <support/test-pointer.h>
#include "tst-malloc-aux.h"
@@ -93,7 +94,10 @@ test_tcache (void *closure)
free (b);
free (c);
- /* Corrupt the pointer with a random value, and avoid optimizations. */
+ /* Corrupt the pointer with a random value, and avoid optimizations.
+ If memory tagging is used, we need to make sure that tag in ptr
+ is cleared. */
+ c = support_ptr_after_free (c);
printf ("Before: c=%p, c[0]=%p\n", c, ((void **)c)[0]);
memset (c, mask & 0xFF, size);
printf ("After: c=%p, c[0]=%p\n", c, ((void **)c)[0]);
@@ -19,6 +19,8 @@
#include <malloc.h>
#include <string.h>
+#include <support/test-pointer.h>
+
static int
do_test (void)
{
@@ -36,6 +38,10 @@ do_test (void)
free (a); // puts in tcache
+ /* If memory tagging is used, we need to make sure that tag in ptr
+ is cleared. */
+ a = support_ptr_after_free (a);
+
/* A is now free and contains the key we use to detect in-tcache.
Copy the key to the other chunks. */
memcpy (b, a, 32);
similarity index 77%
rename from support/address-diff.h
rename to support/test-pointer.h
@@ -1,4 +1,4 @@
-/* Support functions for pointer arithmetic.
+/* Support functions for tests that check pointers.
Copyright (C) 2026 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -16,12 +16,16 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#ifndef _POINTER_ARITH_H
-#define _POINTER_ARITH_H 1
+#ifndef _SUPPORT_TEST_POINTER_H
+#define _SUPPORT_TEST_POINTER_H 1
#include <stddef.h>
/* Returns difference in bytes between addresses of two pointers. */
ptrdiff_t support_address_diff (const void *lhs, const void *rhs);
-#endif /* _POINTER_ARITH_H */
+/* Returns pointer suitable for tests that rely on use-after-free
+ behaviour. */
+void *support_ptr_after_free (void *ptr);
+
+#endif /* _SUPPORT_TEST_POINTER_H */
@@ -111,5 +111,6 @@ endif # malloc directory
ifeq ($(subdir),support)
libsupport-sysdep_routines += \
support-address-diff \
+ support-use-after-free \
# libsupport-sysdep_routines
endif
@@ -16,7 +16,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include "address-diff.h"
+#include "test-pointer.h"
#include <sys/ifunc.h>
#include <sys/auxv.h>
new file mode 100644
@@ -0,0 +1,47 @@
+/* Support functions testing malloc: aarch64 version.
+ Copyright (C) 2026 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 "test-pointer.h"
+
+#include <sys/ifunc.h>
+#include <sys/auxv.h>
+
+/* This version clears bits 59:56 (4 bits) to remove possible
+ MTE tag from the pointer without trying to access memory
+ that this pointer points to. */
+static void *ptr_after_free_mte (void *ptr)
+{
+ return (void *)((uintptr_t)ptr & ~(0xfull << 56ull));
+}
+
+static void *ptr_after_free_generic (void *ptr)
+{
+ return ptr;
+}
+
+static void * __attribute__ ((unused))
+ptr_after_free_resolver (unsigned long a0, const unsigned long *a1)
+{
+ unsigned long hwcap2 = __ifunc_hwcap (_IFUNC_ARG_AT_HWCAP2, a0, a1);
+ if (hwcap2 & HWCAP2_MTE)
+ return (void *)ptr_after_free_mte;
+ return (void *)ptr_after_free_generic;
+}
+
+void *support_ptr_after_free (void *ptr)
+__attribute__ ((ifunc ("ptr_after_free_resolver")));
\ No newline at end of file
@@ -57,5 +57,6 @@ endif
ifeq ($(subdir),support)
libsupport-sysdep_routines += \
support-address-diff \
+ support-use-after-free \
# libsupport-sysdep_routines
endif
@@ -16,7 +16,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include "address-diff.h"
+#include "test-pointer.h"
#include <libc-pointer-arith.h>
new file mode 100644
@@ -0,0 +1,24 @@
+/* Support functions testing malloc: generic version.
+ Copyright (C) 2026 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 "test-pointer.h"
+
+void *support_ptr_after_free (void *ptr)
+{
+ return ptr;
+}