[LTP] [PATCH] lapi/tls: reserve pre-TCB space to avoid undefined behavior in clone10.c
Changwei Zou
changwei.zou@canonical.com
Sat Feb 7 15:59:42 CET 2026
Allocate extra space before the TLS area to hold a struct pthread, ensuring
THREAD_SELF->cancelhandling is initialized to 0. This prevents undefined
behavior in __pthread_disable_asynccancel(), which is called at thread
cancellation points such as write().
Without this, touch_tls_in_child() could get stuck in tst_res().
(gdb) bt
0 futex_wait () at ../sysdeps/nptl/futex-internal.h:141
1 futex_wait_simple () at ../sysdeps/nptl/futex-internal.h:172
2 __libc_disable_asynccancel () at ../nptl/cancellation.c:100
3 __GI___libc_write () at ../sysdeps/unix/sysv/linux/write.c:26
4 __GI___libc_write () at ../sysdeps/unix/sysv/linux/write.c:24
5 print_result () at tst_test.c:387
6 tst_vres_ () at tst_test.c:401
7 tst_res_ () at tst_test.c:512
8 touch_tls_in_child (arg=<optimized out>) at clone10.c:48
9 thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78
Signed-off-by: Changwei Zou <changwei.zou@canonical.com>
---
include/lapi/tls.h | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/include/lapi/tls.h b/include/lapi/tls.h
index 468fe3086..7f2fa18a1 100644
--- a/include/lapi/tls.h
+++ b/include/lapi/tls.h
@@ -22,6 +22,15 @@
#define TLS_SIZE 4096
#define TLS_ALIGN 16
+/*
+ * Space allocated large enough to hold a struct pthread.
+ *
+ * Zero-initialized to ensure THREAD_SELF->cancelhandling starts at 0,
+ * avoiding undefined behavior (e.g., in clone10.c) in __pthread_disable_asynccancel(),
+ * which is called at thread cancellation points such as write().
+ */
+#define TLS_PRE_TCB_SIZE (TLS_ALIGN * 256)
+
#if defined(__x86_64__)
typedef struct {
void *tcb;
@@ -36,10 +45,11 @@ extern void *tls_ptr;
static inline void *allocate_tls_area(void)
{
- void *tls_area = aligned_alloc(TLS_ALIGN, TLS_SIZE);
+ char *tls_area = aligned_alloc(TLS_ALIGN, TLS_PRE_TCB_SIZE + TLS_SIZE);
if (!tls_area)
tst_brk(TBROK | TERRNO, "aligned_alloc failed");
- memset(tls_area, 0, TLS_SIZE);
+ memset(tls_area, 0, TLS_PRE_TCB_SIZE + TLS_SIZE);
+ tls_area += TLS_PRE_TCB_SIZE;
#if defined(__x86_64__)
tcb_t *tcb = (tcb_t *)tls_area;
@@ -59,7 +69,7 @@ static inline void free_tls(void)
{
usleep(10000);
if (tls_ptr) {
- free(tls_ptr);
+ free(((char *)tls_ptr) - TLS_PRE_TCB_SIZE);
tls_ptr = NULL;
}
}
--
2.43.0
More information about the ltp
mailing list