[LTP] [PATCH v7] Add tls parameter and flag:CLONE_SETTLS cover for clone and clone3 syscall

Li Wang liwang@redhat.com
Wed Jun 4 08:33:05 CEST 2025


On Thu, May 29, 2025 at 5:22 PM chunfuwen via ltp <ltp@lists.linux.it>
wrote:

> tls parameter and related flag:CLONE_SETTLS are missed in the testing,
> so add them into existed test case
>
> Signed-off-by: chunfuwen <chwen@redhat.com>
> ---
> Changes in v7:
> - remove unnecessary in verify_tls()
> - add CFLAGS += -fsanitize=address in Makefile to fix memory double free
>   issue
>
> Changes in v6:
> - update flag to effective combination
> - combine x86_64 with other arches
> - rename child function
> - remove inproper exit
> - remove unused code lines
> - remove sleep statement
>
> Changes in v5:
> - wrap duplicate code into one single methold
> - remove duplicately malloc
>
> Changes in v4:
> - remove riscv and loongarch definition
>
> Changes in v3:
> - fix missing head file for x86
>
> Changes in v2:
> - create separate files for clone and clone3
>
> ---
>  runtest/syscalls                            |   2 +
>  testcases/kernel/syscalls/clone/.gitignore  |   1 +
>  testcases/kernel/syscalls/clone/Makefile    |   2 +
>  testcases/kernel/syscalls/clone/clone10.c   | 137 +++++++++++++++++
>  testcases/kernel/syscalls/clone3/.gitignore |   1 +
>  testcases/kernel/syscalls/clone3/clone304.c | 158 ++++++++++++++++++++
>  6 files changed, 301 insertions(+)
>  create mode 100644 testcases/kernel/syscalls/clone/clone10.c
>  create mode 100644 testcases/kernel/syscalls/clone3/clone304.c
>
> diff --git a/runtest/syscalls b/runtest/syscalls
> index 844ae7a13..10f64270a 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -122,10 +122,12 @@ clone06 clone06
>  clone07 clone07
>  clone08 clone08
>  clone09 clone09
> +clone10 clone10
>
>  clone301 clone301
>  clone302 clone302
>  clone303 clone303
> +clone304 clone304
>
>  close01 close01
>  close02 close02
> diff --git a/testcases/kernel/syscalls/clone/.gitignore
> b/testcases/kernel/syscalls/clone/.gitignore
> index 900cac19c..adfb8257d 100644
> --- a/testcases/kernel/syscalls/clone/.gitignore
> +++ b/testcases/kernel/syscalls/clone/.gitignore
> @@ -7,3 +7,4 @@
>  /clone07
>  /clone08
>  /clone09
> +/clone10
> diff --git a/testcases/kernel/syscalls/clone/Makefile
> b/testcases/kernel/syscalls/clone/Makefile
> index 1957711b0..5467eb532 100644
> --- a/testcases/kernel/syscalls/clone/Makefile
> +++ b/testcases/kernel/syscalls/clone/Makefile
> @@ -7,4 +7,6 @@ include $(top_srcdir)/include/mk/testcases.mk
>
>  CFLAGS += -Wl,-z,now
>
> +CFLAGS += -fsanitize=address
>

There two problems shown by enabling AddressSanitizer flag, first
is LTP add one more dependency package libasan, Second it reports
DEADLYSIGNAL error in test running that indicates there is a serious
memory issue.

# ./clone10  -i 10
tst_test.c:1953: TINFO: LTP version: 20250530-2-g7aca112
tst_test.c:1956: TINFO: Tested kernel: 6.12.0-89.el10.x86_64 #1 SMP
PREEMPT_DYNAMIC Tue May 27 00:52:07 EDT 2025 x86_64
tst_kconfig.c:88: TINFO: Parsing kernel config
'/lib/modules/6.12.0-89.el10.x86_64/config'
tst_test.c:1774: TINFO: Overall timeout per run is 0h 00m 30s
clone10.c:92: TINFO: Child (PID: 49130, TID: 49131): TLS value set to: 101
clone10.c:111: TPASS: Parent (PID: 49130, TID: 49130): TLS value correct:
100
clone10.c:111: TPASS: Parent (PID: 49130, TID: 49130): TLS value correct:
100
clone10.c:111: TPASS: Parent (PID: 49130, TID: 49130): TLS value correct:
100
clone10.c:92: TINFO: Child (PID: 49130, TID: 49132): TLS value set to: 101
clone10.c:111: TPASS: Parent (PID: 49130, TID: 49130): TLS value correct:
100
AddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerclone10.c:111: TPASS: Parent (PID: 49130,
TID: 49130): TLS value correct: 100
:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
clone10.c:92: TINFO: Child (PID: 49130, TID: 49134): TLS value set to: 101
clone10.c:111: TPASS: Parent (PID: 49130, TID: 49130): TLS value correct:
100
=================================================================
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
:DEADLYSIGNAL
clone10.c:111: TPASS: Parent (PID: 49130, TID: 49130): TLS value correct:
100
clone10.c:92: TINFO: Child (PID: 49130, TID: 49137): TLS value set to: 101
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerclone10.c:111:
TPASS: Parent (PID: 49130, TID: 49130): TLS value correct: 100
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerclone10.c:92:
TINFO: Child (PID: 49130, TID: 49138): TLS value set to: 101
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerclone10.c:111:
TPASS: Parent (PID: 49130, TID: 49130): TLS value correct: 100
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerclone10.c:92: TINFO: Child
(PID: 49130, TID: 49139): TLS value set to: 101
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerclone10.c:111:
TPASS: Parent (PID: 49130, TID: 49130): TLS value correct: 100
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerclone10.c:92: TINFO: Child (PID: 49130, TID: 49140): TLS
value set to: 101
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizerAddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
Test timeouted, sending SIGKILL!
tst_test.c:1846: TINFO: If you are running on slow machine, try exporting
LTP_TIMEOUT_MUL > 1
tst_test.c:1848: TBROK: Test killed! (timeout?)

Summary:
passed   10
failed   0
broken   1
skipped  0
warnings 0



> +
>  include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/kernel/syscalls/clone/clone10.c
> b/testcases/kernel/syscalls/clone/clone10.c
> new file mode 100644
> index 000000000..3d4951993
> --- /dev/null
> +++ b/testcases/kernel/syscalls/clone/clone10.c
> @@ -0,0 +1,137 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2025 Red Hat Inc. All Rights Reserved.
> + * Author: Chunfu Wen <chwen@redhat.com>
> + */
> +
> +/*\
> + * Add tls parameter and flag:CLONE_SETTLS cover for clone
> + */
> +
> +#define _GNU_SOURCE
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <errno.h>
> +#include <sched.h>
> +#include <sys/wait.h>
> +
> +#if defined(__i386__)
> +#include <asm/ldt.h>
> +#endif
> +
> +#include "tst_test.h"
> +#include "clone_platform.h"
> +#include "lapi/syscalls.h"
> +
> +#define TLS_EXP 100
> +#define TLS_SIZE 4096
> +#define TLS_ALIGN 16
> +
> +static __thread int tls_var = 0;
> +
> +static void *tls_ptr;
> +static struct user_desc *tls_desc;
> +static char *child_stack;
> +static volatile int child_done = 0;
> +
> +static int flags = CLONE_THREAD |  CLONE_VM | CLONE_FS | CLONE_FILES |
> CLONE_SIGHAND | CLONE_SETTLS;
> +
> +static void *allocate_tls_area(void)
> +{
> +       void *tls_area = aligned_alloc(TLS_ALIGN, TLS_SIZE);
> +       if (!tls_area)
> +               tst_brk(TBROK | TERRNO, "aligned_alloc failed");
> +       memset(tls_area, 0, TLS_SIZE);
> +
> +       return tls_area;
> +}
> +
> +static void init_tls(void)
> +{
> +#if defined(__x86_64__) || defined(__aarch64__) || defined(__s390x__)
> +       tls_ptr = allocate_tls_area();
> +
> +#elif defined(__i386__)
> +       tls_ptr = allocate_tls_area();
> +       tls_desc = SAFE_MALLOC(sizeof(*tls_desc));
> +       memset(tls_desc, 0, sizeof(*tls_desc));
> +       tls_desc->entry_number = -1;
> +       tls_desc->base_addr = (unsigned long)tls_ptr;
> +       tls_desc->limit = TLS_SIZE;
> +       tls_desc->seg_32bit = 1;
> +       tls_desc->contents = 0;
> +       tls_desc->read_exec_only = 0;
> +       tls_desc->limit_in_pages = 0;
> +       tls_desc->seg_not_present = 0;
> +       tls_desc->useable = 1;
> +
> +#else
> +       tst_brk(TCONF, "Unsupported architecture for TLS");
> +#endif
> +}
> +
> +static void free_tls(void)
> +{
> +#if defined(__x86_64__) || defined(__aarch64__) || defined(__s390x__)
> +       if (tls_ptr) {
> +               free(tls_ptr);
> +               tls_ptr = NULL;
> +       }
> +#elif defined(__i386__)
> +       if (tls_desc) {
> +               free((void *)(uintptr_t)tls_desc->base_addr);
> +               free(tls_desc);
> +               tls_desc = NULL;
> +       }
> +#endif
> +}
> +
> +static int touch_tls_in_child(void *arg LTP_ATTRIBUTE_UNUSED)
> +{
> +       tls_var = TLS_EXP + 1;
> +       tst_res(TINFO, "Child (PID: %d, TID: %d): TLS value set to: %d",
> getpid(),  gettid(), tls_var);
> +
> +       child_done = 1;
> +       return 0;
> +}
> +
> +static void verify_tls(void)
> +{
> +       tls_var = TLS_EXP;
> +
> +       TEST(ltp_clone7(flags, touch_tls_in_child, NULL, CHILD_STACK_SIZE,
> child_stack, NULL, tls_ptr, NULL));
> +
> +       if (TST_RET == -1)
> +               tst_brk(TBROK | TTERRNO, "clone() failed");
> +
> +       while (!child_done)
> +               sched_yield();
> +
> +       if (TLS_EXP == tls_var) {
> +               tst_res(TPASS,
> +                       "Parent (PID: %d, TID: %d): TLS value correct: %d",
> +                       getpid(), gettid(), tls_var);
> +       } else {
> +               tst_res(TFAIL,
> +                       "Parent (PID: %d, TID: %d): TLS value mismatch:
> got %d, expected %d",
> +                       getpid(), gettid(), tls_var, TLS_EXP);
> +       }
> +}
> +
> +static void setup(void)
> +{
> +       child_stack = SAFE_MALLOC(CHILD_STACK_SIZE);
> +       init_tls();
> +}
> +
> +static void cleanup(void)
> +{
> +       free(child_stack);
> +       free_tls();
> +}
> +
> +static struct tst_test test = {
> +       .setup = setup,
> +       .cleanup = cleanup,
> +       .test_all = verify_tls,
> +};
> diff --git a/testcases/kernel/syscalls/clone3/.gitignore
> b/testcases/kernel/syscalls/clone3/.gitignore
> index 10369954b..e9b5312f4 100644
> --- a/testcases/kernel/syscalls/clone3/.gitignore
> +++ b/testcases/kernel/syscalls/clone3/.gitignore
> @@ -1,3 +1,4 @@
>  clone301
>  clone302
>  clone303
> +clone304
> diff --git a/testcases/kernel/syscalls/clone3/clone304.c
> b/testcases/kernel/syscalls/clone3/clone304.c
> new file mode 100644
> index 000000000..c0e815d28
> --- /dev/null
> +++ b/testcases/kernel/syscalls/clone3/clone304.c
> @@ -0,0 +1,158 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2025 Red Hat Inc. All Rights Reserved.
> + * Author: Chunfu Wen <chwen@redhat.com>
> + */
> +
> +/*\
> + * Add tls parameter and flag:CLONE_SETTLS cover for clone3
> + */
> +
> +#define _GNU_SOURCE
> +
> +#include <stdlib.h>
> +#include <sys/wait.h>
> +
> +#if defined(__i386__)
> +#include <asm/ldt.h>
> +#endif
> +
> +#include "tst_test.h"
> +#include "lapi/sched.h"
> +#include "lapi/pidfd.h"
> +
> +#define TLS_EXP 100
> +#define TLS_SIZE 4096
> +#define TLS_ALIGN 16
> +#define CHILD_STACK_SIZE (1024*1024)
> +
> +static int pidfd, child_tid, parent_tid;
> +static struct clone_args *args;
> +static void *tls_ptr;
> +static struct user_desc *tls_desc;
> +static void *child_stack;
> +
> +static volatile int child_done = 0;
> +/* TLS variable to validate in child */
> +static __thread int tls_var = 0;
> +
> +static int test_flags = CLONE_THREAD |  CLONE_VM | CLONE_FS | CLONE_FILES
> | CLONE_SIGHAND | CLONE_SETTLS;
> +
> +static void *allocate_tls_region(void)
> +{
> +       void *tls_area = aligned_alloc(TLS_ALIGN, TLS_SIZE);
> +       if (!tls_area) {
> +               perror("aligned_alloc");
> +               exit(EXIT_FAILURE);
> +       }
> +       memset(tls_area, 0, TLS_SIZE);
> +       return tls_area;
> +}
> +
> +static void initialize_tls(void)
> +{
> +#if defined(__x86_64__) || defined(__aarch64__) || defined(__s390x__)
> +       tls_ptr = allocate_tls_region();
> +
> +#elif defined(__i386__)
> +       /* x86 32-bit: TLS is a struct user_desc */
> +       tls_ptr = allocate_tls_region();
> +       tls_desc = SAFE_MALLOC(sizeof(*tls_desc));
> +       memset(tls_desc, 0, sizeof(*tls_desc));
> +       tls_desc->entry_number = -1;
> +       tls_desc->base_addr = (unsigned long)tls_ptr;
> +       tls_desc->limit = TLS_SIZE;
> +       tls_desc->seg_32bit = 1;
> +       tls_desc->contents = 0;
> +       tls_desc->read_exec_only = 0;
> +       tls_desc->limit_in_pages = 0;
> +       tls_desc->seg_not_present = 0;
> +       tls_desc->useable = 1;
> +
> +#else
> +       tst_brk(TCONF, "This architecture does not support TLS");
> +#endif
> +}
> +
> +static void free_tls(void)
> +{
> +#if defined(__x86_64__) || defined(__aarch64__) || defined(__s390x__)
> +       if (tls_ptr) {
> +               free(tls_ptr);
> +       }
> +#elif defined(__i386__)
> +       if (tls_desc) {
> +               free((void *)(uintptr_t)tls_desc->base_addr);
> +               free(tls_desc);
> +       }
> +#endif
> +}
> +
> +static int check_tls_in_child(void)
> +{
> +       tls_var = TLS_EXP + 1;
> +       tst_res(TINFO, "Child (PID: %d, TID: %d): TLS value set to: %d",
> getpid(),  gettid(), tls_var);
> +
> +       child_done = 1;
> +       tst_syscall(__NR_exit, 0);
> +       return 0;
> +}
> +
> +static void run(void)
> +{
> +       pid_t pid;
> +       int status;
> +       tls_var = TLS_EXP;
> +
> +       args->flags = test_flags;
> +       args->pidfd = (uint64_t)(&pidfd);
> +       args->child_tid = (uint64_t)(&child_tid);
> +       args->parent_tid = (uint64_t)(&parent_tid);
> +       args->stack = (uint64_t)(child_stack);
> +       args->stack_size = CHILD_STACK_SIZE;
> +       args->tls = (uint64_t)tls_ptr;
> +
> +       TEST(pid = clone3(args, sizeof(*args)));
> +
> +       if (TST_RET == -1)
> +               tst_brk(TBROK | TTERRNO, "clone() failed");
> +
> +       if (!pid)
> +               check_tls_in_child();
> +
> +       while (!child_done)
> +               sched_yield();
> +
> +       if (TLS_EXP == tls_var) {
> +               tst_res(TPASS,
> +                       "Parent (PID: %d, TID: %d): TLS value correct: %d",
> +                       getpid(), gettid(), tls_var);
> +       } else {
> +               tst_res(TFAIL,
> +                       "Parent (PID: %d, TID: %d): TLS value mismatch:
> got %d, expected %d",
> +                       getpid(), gettid(), tls_var, TLS_EXP);
> +       }
> +}
> +
> +static void setup(void)
> +{
> +       clone3_supported_by_kernel();
> +       child_stack = SAFE_MALLOC(CHILD_STACK_SIZE);
> +       initialize_tls();
> +}
> +
> +static void cleanup(void)
> +{
> +       free(child_stack);
> +       free_tls();
> +}
> +
> +static struct tst_test test = {
> +       .setup = setup,
> +       .cleanup = cleanup,
> +       .test_all = run,
> +       .bufs = (struct tst_buffers []) {
> +               {&args, .size = sizeof(*args)},
> +               {},
> +       }
> +};
> --
> 2.43.5
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
>
>

-- 
Regards,
Li Wang


More information about the ltp mailing list