[LTP] [PATCH] lapi/tls: reserve pre-TCB space to avoid undefined behavior in clone10.c
Changwei Zou
changwei.zou@canonical.com
Mon Feb 9 10:42:28 CET 2026
Hi Petr,
Additional details can be found on the following page:
https://bugs.launchpad.net/ubuntu-kernel-tests/+bug/2139127/comments/1
Thank you very much.
Kind regards,
Changwei
On 2/9/26 18:51, Petr Vorel wrote:
> Hi Changwei,
>
>> 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().
> LGTM, but I'd prefer others had a look on it.
> Acked-by: Petr Vorel<pvorel@suse.cz>
>
> BTW clone10.c segfaults w/a the patch when run with more iterations:
>
> ./clone10 -i200
> clone10.c:48: TINFO: Child (PID: 4271, TID: 4285): TLS value set to: 101
> clone10.c:68: TPASS: Parent (PID: 4271, TID: 4271): TLS value correct: 100
> clone10.c:48: TINFO: Child (PID: 4271, TID: 4286): TLS value set to: 101
> clone10.c:68: TPASS: Parent (PID: 4271, TID: 4271): TLS value correct: 100
> tst_test.c:1953: TBROK: Test killed by SIGSEGV!
>
> Summary:
> passed 15
> failed 0
> broken 1
> skipped 0
> warnings 0
>
> Kind regards,
> Petr
>
>> (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>) atclone10.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;
>> }
>> }
More information about the ltp
mailing list