[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