diff mbox series

Add tls parameter and flag:CLONE_SETTLS cover for clone and clone3 syscall

Message ID 20250422093257.299066-1-chwen@redhat.com
State Rejected
Headers show
Series Add tls parameter and flag:CLONE_SETTLS cover for clone and clone3 syscall | expand

Checks

Context Check Description
ltpci/debian_stable_s390x-linux-gnu-gcc_s390x success success
ltpci/debian_stable_powerpc64le-linux-gnu-gcc_ppc64el success success
ltpci/debian_stable_aarch64-linux-gnu-gcc_arm64 success success
ltpci/debian_stable_gcc success success
ltpci/ubuntu_jammy_gcc success success
ltpci/fedora_latest_clang success success
ltpci/debian_stable_gcc success success
ltpci/ubuntu_bionic_gcc success success
ltpci/alpine_latest_gcc success success
ltpci/quay-io-centos-centos_stream9_gcc success success
ltpci/debian_testing_gcc success success
ltpci/opensuse-archive_42-2_gcc success success
ltpci/debian_oldstable_gcc success success
ltpci/opensuse-leap_latest_gcc success success
ltpci/debian_oldstable_clang success success
ltpci/debian_testing_clang success success

Commit Message

chunfuwen April 22, 2025, 9:32 a.m. UTC
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>
---
 testcases/kernel/syscalls/clone/clone08.c   | 40 ++++++++++++++++++---
 testcases/kernel/syscalls/clone3/clone301.c | 36 ++++++++++++++++---
 2 files changed, 67 insertions(+), 9 deletions(-)

Comments

chunfuwen April 24, 2025, 5:25 a.m. UTC | #1
Hello Maintainers,

Could someone please drop a review of this patch?

Best Regards,
Chunfu Wen

On Tue, Apr 22, 2025 at 5:33 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>
> ---
>  testcases/kernel/syscalls/clone/clone08.c   | 40 ++++++++++++++++++---
>  testcases/kernel/syscalls/clone3/clone301.c | 36 ++++++++++++++++---
>  2 files changed, 67 insertions(+), 9 deletions(-)
>
> diff --git a/testcases/kernel/syscalls/clone/clone08.c
> b/testcases/kernel/syscalls/clone/clone08.c
> index dd97f3ff1..f5a8119a8 100644
> --- a/testcases/kernel/syscalls/clone/clone08.c
> +++ b/testcases/kernel/syscalls/clone/clone08.c
> @@ -17,7 +17,11 @@
>  #include "lapi/syscalls.h"
>  #include "lapi/futex.h"
>
> +#define TLS_SIZE 4096
> +#define TLS_ALIGN 16
> +
>  static pid_t ptid, ctid, tgid;
> +static void *tls_ptr;
>  static void *child_stack;
>
>  static void test_clone_parent(int t);
> @@ -32,6 +36,9 @@ static int child_clone_parent_settid(void *);
>  static void test_clone_thread(int t);
>  static int child_clone_thread(void *);
>
> +/* TLS variable to validate in child */
> +static __thread int tls_test_var = 12345;
> +
>  /*
>   * Children cloned with CLONE_VM should avoid using any functions that
>   * might require dl_runtime_resolve, because they share thread-local
> @@ -46,14 +53,14 @@ static struct test_case {
>         void (*testfunc)(int);
>         int (*do_child)(void *);
>  } test_cases[] = {
> -       {"CLONE_PARENT", CLONE_PARENT | SIGCHLD,
> +       {"CLONE_PARENT", CLONE_PARENT | CLONE_SETTLS | SIGCHLD,
>          test_clone_parent, child_clone_parent},
> -       {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD,
> +       {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | CLONE_SETTLS | SIGCHLD,
>          test_clone_tid, child_clone_child_settid},
> -       {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | SIGCHLD,
> +       {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM |
> CLONE_SETTLS | SIGCHLD,
>          test_clone_tid, child_clone_parent_settid},
>         {"CLONE_THREAD", CLONE_THREAD | CLONE_SIGHAND | CLONE_VM |
> -        CLONE_CHILD_CLEARTID | SIGCHLD,
> +        CLONE_CHILD_CLEARTID | CLONE_SETTLS | SIGCHLD,
>          test_clone_thread, child_clone_thread},
>  };
>
> @@ -66,17 +73,24 @@ static void do_test(unsigned int i)
>  static void setup(void)
>  {
>         child_stack = SAFE_MALLOC(CHILD_STACK_SIZE);
> +       tls_ptr = aligned_alloc(TLS_ALIGN, TLS_SIZE);
> +       if (!tls_ptr) {
> +               perror("aligned_alloc");
> +               exit(EXIT_FAILURE);
> +       }
> +       memset(tls_ptr, 0, TLS_SIZE);
>  }
>
>  static void cleanup(void)
>  {
>         free(child_stack);
> +       free(tls_ptr);
>  }
>
>  static long clone_child(const struct test_case *t)
>  {
>         TEST(ltp_clone7(t->flags, t->do_child, NULL, CHILD_STACK_SIZE,
> -               child_stack, &ptid, NULL, &ctid));
> +               child_stack, &ptid, tls_ptr, &ctid));
>
>         if (TST_RET == -1 && TTERRNO == ENOSYS)
>                 tst_brk(TCONF, "clone does not support 7 args");
> @@ -87,6 +101,14 @@ static long clone_child(const struct test_case *t)
>         return TST_RET;
>  }
>
> +static void validate_tls(void)
> +{
> +       if (tls_test_var == 12345)
> +               tst_res(TPASS, "Child TLS variable has expected value");
> +       else
> +               tst_res(TFAIL, "Child TLS variable corrupted or not set");
> +}
> +
>  static void test_clone_parent(int t)
>  {
>         pid_t child;
> @@ -102,6 +124,8 @@ static void test_clone_parent(int t)
>
>  static int child_clone_parent(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +       validate_tls();
> +
>         if (parent_ppid == getppid()) {
>                 tst_res(TPASS, "clone and forked child has the same
> parent");
>         } else {
> @@ -120,6 +144,8 @@ static void test_clone_tid(int t)
>
>  static int child_clone_child_settid(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +       validate_tls();
> +
>         if (ctid == tst_syscall(__NR_getpid))
>                 tst_res(TPASS, "clone() correctly set ctid");
>         else
> @@ -130,6 +156,8 @@ static int child_clone_child_settid(void *arg
> LTP_ATTRIBUTE_UNUSED)
>
>  static int child_clone_parent_settid(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +       validate_tls();
> +
>         if (ptid == tst_syscall(__NR_getpid))
>                 tst_res(TPASS, "clone() correctly set ptid");
>         else
> @@ -175,6 +203,8 @@ static void test_clone_thread(int t)
>
>  static int child_clone_thread(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +       validate_tls();
> +
>         if (tgid == tst_syscall(__NR_getpid))
>                 tst_res(TPASS, "clone has the same thread id");
>         else
> diff --git a/testcases/kernel/syscalls/clone3/clone301.c
> b/testcases/kernel/syscalls/clone3/clone301.c
> index deed30b9f..9571c9f5c 100644
> --- a/testcases/kernel/syscalls/clone3/clone301.c
> +++ b/testcases/kernel/syscalls/clone3/clone301.c
> @@ -18,22 +18,38 @@
>
>  #define CHILD_SIGNAL   SIGUSR1
>  #define DATA   777
> +#define TLS_SIZE 4096
> +#define TLS_ALIGN 16
>
>  static int pidfd, child_tid, parent_tid, parent_received_signal;
>  static volatile int child_received_signal, child_data;
>  static struct clone_args *args;
>
> +/* TLS variable to validate in child */
> +static __thread int tls_test_var = 12345;
> +
>  static struct tcase {
>         uint64_t flags;
>         int exit_signal;
>  } tcases[] = {
>         {0, SIGCHLD},
>         {0, SIGUSR2},
> -       {CLONE_FS, SIGCHLD},
> -       {CLONE_NEWPID, SIGCHLD},
> -       {CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_PIDFD, SIGCHLD},
> +       {CLONE_FS | CLONE_SETTLS, SIGCHLD},
> +       {CLONE_NEWPID | CLONE_SETTLS, SIGCHLD},
> +       {CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_PIDFD |
> CLONE_SETTLS, SIGCHLD},
>  };
>
> +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 parent_rx_signal(int sig)
>  {
>         parent_received_signal = sig;
> @@ -67,6 +83,13 @@ static void do_child(int clone_pidfd)
>  {
>         int count = 1000;
>
> +       /* Validate TLS usage */
> +       if (tls_test_var == 12345) {
> +               tst_res(TPASS, "Child TLS variable has expected value");
> +       } else {
> +               tst_res(TFAIL, "Child TLS variable corrupted or not set");
> +       }
> +
>         if (clone_pidfd) {
>                 child_received_signal = 0;
>                 child_data = 0;
> @@ -111,6 +134,8 @@ static void run(unsigned int n)
>         int status, clone_pidfd = tc->flags & CLONE_PIDFD;
>         pid_t pid;
>
> +       void *tls_ptr = allocate_tls_region();
> +
>         args->flags = tc->flags;
>         args->pidfd = (uint64_t)(&pidfd);
>         args->child_tid = (uint64_t)(&child_tid);
> @@ -118,7 +143,7 @@ static void run(unsigned int n)
>         args->exit_signal = tc->exit_signal;
>         args->stack = 0;
>         args->stack_size = 0;
> -       args->tls = 0;
> +       args->tls = (uint64_t)tls_ptr;
>
>         parent_received_signal = 0;
>         SAFE_SIGACTION(tc->exit_signal, &psig_action, NULL);
> @@ -126,6 +151,7 @@ static void run(unsigned int n)
>         TEST(pid = clone3(args, sizeof(*args)));
>         if (pid < 0) {
>                 tst_res(TFAIL | TTERRNO, "clone3() failed (%d)", n);
> +               free(tls_ptr);
>                 return;
>         }
>
> @@ -139,11 +165,13 @@ static void run(unsigned int n)
>                 TEST(pidfd_send_signal(pidfd, CHILD_SIGNAL, &uinfo, 0));
>                 if (TST_RET != 0) {
>                         tst_res(TFAIL | TTERRNO, "pidfd_send_signal()
> failed");
> +                       free(tls_ptr);
>                         return;
>                 }
>         }
>
>         SAFE_WAITPID(pid, &status, __WALL);
> +       free(tls_ptr);
>
>         if (!parent_received_signal) {
>                 tst_res(TFAIL, "Parent haven't got signal");
> --
> 2.43.5
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
>
>
Li Wang April 27, 2025, 7:55 a.m. UTC | #2
Hi Chunfu,

According to the manual page:

"CLONE_SETTLS (since Linux 2.5.32):
The interpretation of tls and the resulting effect is architecture
dependent.
On x86, tls is interpreted as a struct user_desc * (see
set_thread_area(2)).
On x86-64 it is the new value to be set for the %fs base register (see the
ARCH_SET_FS argument to arch_prctl(2)).  On architectures with a dedicated
TLS register, it is the new value of that register..."

I'm afraid we shouldn't test CLONE_SETTLS in this way, the tls
interpretation
is arch-dependent, it could fail or behave incorrectly on 32-bit x86 or
non-x86
systems.

And, clone08 was originally intended to test the basic behavior of clone
(such as
TID settings and parent-child relationships) and should not introduce
complex
architecture-related logic.

So, maybe you can create a new clone10.c file to write a dedicated test
for CLONE_SETTLS and add architecture-specific handling.


On Tue, Apr 22, 2025 at 5:33 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>
> ---
>  testcases/kernel/syscalls/clone/clone08.c   | 40 ++++++++++++++++++---
>  testcases/kernel/syscalls/clone3/clone301.c | 36 ++++++++++++++++---
>  2 files changed, 67 insertions(+), 9 deletions(-)
>
> diff --git a/testcases/kernel/syscalls/clone/clone08.c
> b/testcases/kernel/syscalls/clone/clone08.c
> index dd97f3ff1..f5a8119a8 100644
> --- a/testcases/kernel/syscalls/clone/clone08.c
> +++ b/testcases/kernel/syscalls/clone/clone08.c
> @@ -17,7 +17,11 @@
>  #include "lapi/syscalls.h"
>  #include "lapi/futex.h"
>
> +#define TLS_SIZE 4096
> +#define TLS_ALIGN 16
> +
>  static pid_t ptid, ctid, tgid;
> +static void *tls_ptr;
>  static void *child_stack;
>
>  static void test_clone_parent(int t);
> @@ -32,6 +36,9 @@ static int child_clone_parent_settid(void *);
>  static void test_clone_thread(int t);
>  static int child_clone_thread(void *);
>
> +/* TLS variable to validate in child */
> +static __thread int tls_test_var = 12345;
> +
>  /*
>   * Children cloned with CLONE_VM should avoid using any functions that
>   * might require dl_runtime_resolve, because they share thread-local
> @@ -46,14 +53,14 @@ static struct test_case {
>         void (*testfunc)(int);
>         int (*do_child)(void *);
>  } test_cases[] = {
> -       {"CLONE_PARENT", CLONE_PARENT | SIGCHLD,
> +       {"CLONE_PARENT", CLONE_PARENT | CLONE_SETTLS | SIGCHLD,
>          test_clone_parent, child_clone_parent},
> -       {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD,
> +       {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | CLONE_SETTLS | SIGCHLD,
>          test_clone_tid, child_clone_child_settid},
> -       {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | SIGCHLD,
> +       {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM |
> CLONE_SETTLS | SIGCHLD,
>          test_clone_tid, child_clone_parent_settid},
>         {"CLONE_THREAD", CLONE_THREAD | CLONE_SIGHAND | CLONE_VM |
> -        CLONE_CHILD_CLEARTID | SIGCHLD,
> +        CLONE_CHILD_CLEARTID | CLONE_SETTLS | SIGCHLD,
>          test_clone_thread, child_clone_thread},
>  };
>
> @@ -66,17 +73,24 @@ static void do_test(unsigned int i)
>  static void setup(void)
>  {
>         child_stack = SAFE_MALLOC(CHILD_STACK_SIZE);
> +       tls_ptr = aligned_alloc(TLS_ALIGN, TLS_SIZE);
> +       if (!tls_ptr) {
> +               perror("aligned_alloc");
> +               exit(EXIT_FAILURE);
> +       }
> +       memset(tls_ptr, 0, TLS_SIZE);
>  }
>
>  static void cleanup(void)
>  {
>         free(child_stack);
> +       free(tls_ptr);
>  }
>
>  static long clone_child(const struct test_case *t)
>  {
>         TEST(ltp_clone7(t->flags, t->do_child, NULL, CHILD_STACK_SIZE,
> -               child_stack, &ptid, NULL, &ctid));
> +               child_stack, &ptid, tls_ptr, &ctid));
>
>         if (TST_RET == -1 && TTERRNO == ENOSYS)
>                 tst_brk(TCONF, "clone does not support 7 args");
> @@ -87,6 +101,14 @@ static long clone_child(const struct test_case *t)
>         return TST_RET;
>  }
>
> +static void validate_tls(void)
> +{
> +       if (tls_test_var == 12345)
> +               tst_res(TPASS, "Child TLS variable has expected value");
> +       else
> +               tst_res(TFAIL, "Child TLS variable corrupted or not set");
> +}
> +
>  static void test_clone_parent(int t)
>  {
>         pid_t child;
> @@ -102,6 +124,8 @@ static void test_clone_parent(int t)
>
>  static int child_clone_parent(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +       validate_tls();
> +
>         if (parent_ppid == getppid()) {
>                 tst_res(TPASS, "clone and forked child has the same
> parent");
>         } else {
> @@ -120,6 +144,8 @@ static void test_clone_tid(int t)
>
>  static int child_clone_child_settid(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +       validate_tls();
> +
>         if (ctid == tst_syscall(__NR_getpid))
>                 tst_res(TPASS, "clone() correctly set ctid");
>         else
> @@ -130,6 +156,8 @@ static int child_clone_child_settid(void *arg
> LTP_ATTRIBUTE_UNUSED)
>
>  static int child_clone_parent_settid(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +       validate_tls();
> +
>         if (ptid == tst_syscall(__NR_getpid))
>                 tst_res(TPASS, "clone() correctly set ptid");
>         else
> @@ -175,6 +203,8 @@ static void test_clone_thread(int t)
>
>  static int child_clone_thread(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
> +       validate_tls();
> +
>         if (tgid == tst_syscall(__NR_getpid))
>                 tst_res(TPASS, "clone has the same thread id");
>         else
> diff --git a/testcases/kernel/syscalls/clone3/clone301.c
> b/testcases/kernel/syscalls/clone3/clone301.c
> index deed30b9f..9571c9f5c 100644
> --- a/testcases/kernel/syscalls/clone3/clone301.c
> +++ b/testcases/kernel/syscalls/clone3/clone301.c
> @@ -18,22 +18,38 @@
>
>  #define CHILD_SIGNAL   SIGUSR1
>  #define DATA   777
> +#define TLS_SIZE 4096
> +#define TLS_ALIGN 16
>
>  static int pidfd, child_tid, parent_tid, parent_received_signal;
>  static volatile int child_received_signal, child_data;
>  static struct clone_args *args;
>
> +/* TLS variable to validate in child */
> +static __thread int tls_test_var = 12345;
> +
>  static struct tcase {
>         uint64_t flags;
>         int exit_signal;
>  } tcases[] = {
>         {0, SIGCHLD},
>         {0, SIGUSR2},
> -       {CLONE_FS, SIGCHLD},
> -       {CLONE_NEWPID, SIGCHLD},
> -       {CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_PIDFD, SIGCHLD},
> +       {CLONE_FS | CLONE_SETTLS, SIGCHLD},
> +       {CLONE_NEWPID | CLONE_SETTLS, SIGCHLD},
> +       {CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_PIDFD |
> CLONE_SETTLS, SIGCHLD},
>  };
>
> +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 parent_rx_signal(int sig)
>  {
>         parent_received_signal = sig;
> @@ -67,6 +83,13 @@ static void do_child(int clone_pidfd)
>  {
>         int count = 1000;
>
> +       /* Validate TLS usage */
> +       if (tls_test_var == 12345) {
> +               tst_res(TPASS, "Child TLS variable has expected value");
> +       } else {
> +               tst_res(TFAIL, "Child TLS variable corrupted or not set");
> +       }
> +
>         if (clone_pidfd) {
>                 child_received_signal = 0;
>                 child_data = 0;
> @@ -111,6 +134,8 @@ static void run(unsigned int n)
>         int status, clone_pidfd = tc->flags & CLONE_PIDFD;
>         pid_t pid;
>
> +       void *tls_ptr = allocate_tls_region();
> +
>         args->flags = tc->flags;
>         args->pidfd = (uint64_t)(&pidfd);
>         args->child_tid = (uint64_t)(&child_tid);
> @@ -118,7 +143,7 @@ static void run(unsigned int n)
>         args->exit_signal = tc->exit_signal;
>         args->stack = 0;
>         args->stack_size = 0;
> -       args->tls = 0;
> +       args->tls = (uint64_t)tls_ptr;
>
>         parent_received_signal = 0;
>         SAFE_SIGACTION(tc->exit_signal, &psig_action, NULL);
> @@ -126,6 +151,7 @@ static void run(unsigned int n)
>         TEST(pid = clone3(args, sizeof(*args)));
>         if (pid < 0) {
>                 tst_res(TFAIL | TTERRNO, "clone3() failed (%d)", n);
> +               free(tls_ptr);
>                 return;
>         }
>
> @@ -139,11 +165,13 @@ static void run(unsigned int n)
>                 TEST(pidfd_send_signal(pidfd, CHILD_SIGNAL, &uinfo, 0));
>                 if (TST_RET != 0) {
>                         tst_res(TFAIL | TTERRNO, "pidfd_send_signal()
> failed");
> +                       free(tls_ptr);
>                         return;
>                 }
>         }
>
>         SAFE_WAITPID(pid, &status, __WALL);
> +       free(tls_ptr);
>
>         if (!parent_received_signal) {
>                 tst_res(TFAIL, "Parent haven't got signal");
> --
> 2.43.5
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
>
>
chunfuwen April 28, 2025, 3:18 p.m. UTC | #3
Hello,

Thanks for reviewing!
The below issues will be addressed in v2 patch.

Chunfu Wen

On Sun, Apr 27, 2025 at 3:56 PM Li Wang <liwang@redhat.com> wrote:

> Hi Chunfu,
>
> According to the manual page:
>
> "CLONE_SETTLS (since Linux 2.5.32):
> The interpretation of tls and the resulting effect is architecture
> dependent.
> On x86, tls is interpreted as a struct user_desc * (see
> set_thread_area(2)).
> On x86-64 it is the new value to be set for the %fs base register (see the
> ARCH_SET_FS argument to arch_prctl(2)).  On architectures with a dedicated
> TLS register, it is the new value of that register..."
>
> I'm afraid we shouldn't test CLONE_SETTLS in this way, the tls
> interpretation
> is arch-dependent, it could fail or behave incorrectly on 32-bit x86 or
> non-x86
> systems.
>
> And, clone08 was originally intended to test the basic behavior of clone
> (such as
> TID settings and parent-child relationships) and should not introduce
> complex
> architecture-related logic.
>
> So, maybe you can create a new clone10.c file to write a dedicated test
> for CLONE_SETTLS and add architecture-specific handling.
>
>
> On Tue, Apr 22, 2025 at 5:33 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>
>> ---
>>  testcases/kernel/syscalls/clone/clone08.c   | 40 ++++++++++++++++++---
>>  testcases/kernel/syscalls/clone3/clone301.c | 36 ++++++++++++++++---
>>  2 files changed, 67 insertions(+), 9 deletions(-)
>>
>> diff --git a/testcases/kernel/syscalls/clone/clone08.c
>> b/testcases/kernel/syscalls/clone/clone08.c
>> index dd97f3ff1..f5a8119a8 100644
>> --- a/testcases/kernel/syscalls/clone/clone08.c
>> +++ b/testcases/kernel/syscalls/clone/clone08.c
>> @@ -17,7 +17,11 @@
>>  #include "lapi/syscalls.h"
>>  #include "lapi/futex.h"
>>
>> +#define TLS_SIZE 4096
>> +#define TLS_ALIGN 16
>> +
>>  static pid_t ptid, ctid, tgid;
>> +static void *tls_ptr;
>>  static void *child_stack;
>>
>>  static void test_clone_parent(int t);
>> @@ -32,6 +36,9 @@ static int child_clone_parent_settid(void *);
>>  static void test_clone_thread(int t);
>>  static int child_clone_thread(void *);
>>
>> +/* TLS variable to validate in child */
>> +static __thread int tls_test_var = 12345;
>> +
>>  /*
>>   * Children cloned with CLONE_VM should avoid using any functions that
>>   * might require dl_runtime_resolve, because they share thread-local
>> @@ -46,14 +53,14 @@ static struct test_case {
>>         void (*testfunc)(int);
>>         int (*do_child)(void *);
>>  } test_cases[] = {
>> -       {"CLONE_PARENT", CLONE_PARENT | SIGCHLD,
>> +       {"CLONE_PARENT", CLONE_PARENT | CLONE_SETTLS | SIGCHLD,
>>          test_clone_parent, child_clone_parent},
>> -       {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD,
>> +       {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | CLONE_SETTLS |
>> SIGCHLD,
>>          test_clone_tid, child_clone_child_settid},
>> -       {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | SIGCHLD,
>> +       {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM |
>> CLONE_SETTLS | SIGCHLD,
>>          test_clone_tid, child_clone_parent_settid},
>>         {"CLONE_THREAD", CLONE_THREAD | CLONE_SIGHAND | CLONE_VM |
>> -        CLONE_CHILD_CLEARTID | SIGCHLD,
>> +        CLONE_CHILD_CLEARTID | CLONE_SETTLS | SIGCHLD,
>>          test_clone_thread, child_clone_thread},
>>  };
>>
>> @@ -66,17 +73,24 @@ static void do_test(unsigned int i)
>>  static void setup(void)
>>  {
>>         child_stack = SAFE_MALLOC(CHILD_STACK_SIZE);
>> +       tls_ptr = aligned_alloc(TLS_ALIGN, TLS_SIZE);
>> +       if (!tls_ptr) {
>> +               perror("aligned_alloc");
>> +               exit(EXIT_FAILURE);
>> +       }
>> +       memset(tls_ptr, 0, TLS_SIZE);
>>  }
>>
>>  static void cleanup(void)
>>  {
>>         free(child_stack);
>> +       free(tls_ptr);
>>  }
>>
>>  static long clone_child(const struct test_case *t)
>>  {
>>         TEST(ltp_clone7(t->flags, t->do_child, NULL, CHILD_STACK_SIZE,
>> -               child_stack, &ptid, NULL, &ctid));
>> +               child_stack, &ptid, tls_ptr, &ctid));
>>
>>         if (TST_RET == -1 && TTERRNO == ENOSYS)
>>                 tst_brk(TCONF, "clone does not support 7 args");
>> @@ -87,6 +101,14 @@ static long clone_child(const struct test_case *t)
>>         return TST_RET;
>>  }
>>
>> +static void validate_tls(void)
>> +{
>> +       if (tls_test_var == 12345)
>> +               tst_res(TPASS, "Child TLS variable has expected value");
>> +       else
>> +               tst_res(TFAIL, "Child TLS variable corrupted or not set");
>> +}
>> +
>>  static void test_clone_parent(int t)
>>  {
>>         pid_t child;
>> @@ -102,6 +124,8 @@ static void test_clone_parent(int t)
>>
>>  static int child_clone_parent(void *arg LTP_ATTRIBUTE_UNUSED)
>>  {
>> +       validate_tls();
>> +
>>         if (parent_ppid == getppid()) {
>>                 tst_res(TPASS, "clone and forked child has the same
>> parent");
>>         } else {
>> @@ -120,6 +144,8 @@ static void test_clone_tid(int t)
>>
>>  static int child_clone_child_settid(void *arg LTP_ATTRIBUTE_UNUSED)
>>  {
>> +       validate_tls();
>> +
>>         if (ctid == tst_syscall(__NR_getpid))
>>                 tst_res(TPASS, "clone() correctly set ctid");
>>         else
>> @@ -130,6 +156,8 @@ static int child_clone_child_settid(void *arg
>> LTP_ATTRIBUTE_UNUSED)
>>
>>  static int child_clone_parent_settid(void *arg LTP_ATTRIBUTE_UNUSED)
>>  {
>> +       validate_tls();
>> +
>>         if (ptid == tst_syscall(__NR_getpid))
>>                 tst_res(TPASS, "clone() correctly set ptid");
>>         else
>> @@ -175,6 +203,8 @@ static void test_clone_thread(int t)
>>
>>  static int child_clone_thread(void *arg LTP_ATTRIBUTE_UNUSED)
>>  {
>> +       validate_tls();
>> +
>>         if (tgid == tst_syscall(__NR_getpid))
>>                 tst_res(TPASS, "clone has the same thread id");
>>         else
>> diff --git a/testcases/kernel/syscalls/clone3/clone301.c
>> b/testcases/kernel/syscalls/clone3/clone301.c
>> index deed30b9f..9571c9f5c 100644
>> --- a/testcases/kernel/syscalls/clone3/clone301.c
>> +++ b/testcases/kernel/syscalls/clone3/clone301.c
>> @@ -18,22 +18,38 @@
>>
>>  #define CHILD_SIGNAL   SIGUSR1
>>  #define DATA   777
>> +#define TLS_SIZE 4096
>> +#define TLS_ALIGN 16
>>
>>  static int pidfd, child_tid, parent_tid, parent_received_signal;
>>  static volatile int child_received_signal, child_data;
>>  static struct clone_args *args;
>>
>> +/* TLS variable to validate in child */
>> +static __thread int tls_test_var = 12345;
>> +
>>  static struct tcase {
>>         uint64_t flags;
>>         int exit_signal;
>>  } tcases[] = {
>>         {0, SIGCHLD},
>>         {0, SIGUSR2},
>> -       {CLONE_FS, SIGCHLD},
>> -       {CLONE_NEWPID, SIGCHLD},
>> -       {CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_PIDFD, SIGCHLD},
>> +       {CLONE_FS | CLONE_SETTLS, SIGCHLD},
>> +       {CLONE_NEWPID | CLONE_SETTLS, SIGCHLD},
>> +       {CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_PIDFD |
>> CLONE_SETTLS, SIGCHLD},
>>  };
>>
>> +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 parent_rx_signal(int sig)
>>  {
>>         parent_received_signal = sig;
>> @@ -67,6 +83,13 @@ static void do_child(int clone_pidfd)
>>  {
>>         int count = 1000;
>>
>> +       /* Validate TLS usage */
>> +       if (tls_test_var == 12345) {
>> +               tst_res(TPASS, "Child TLS variable has expected value");
>> +       } else {
>> +               tst_res(TFAIL, "Child TLS variable corrupted or not set");
>> +       }
>> +
>>         if (clone_pidfd) {
>>                 child_received_signal = 0;
>>                 child_data = 0;
>> @@ -111,6 +134,8 @@ static void run(unsigned int n)
>>         int status, clone_pidfd = tc->flags & CLONE_PIDFD;
>>         pid_t pid;
>>
>> +       void *tls_ptr = allocate_tls_region();
>> +
>>         args->flags = tc->flags;
>>         args->pidfd = (uint64_t)(&pidfd);
>>         args->child_tid = (uint64_t)(&child_tid);
>> @@ -118,7 +143,7 @@ static void run(unsigned int n)
>>         args->exit_signal = tc->exit_signal;
>>         args->stack = 0;
>>         args->stack_size = 0;
>> -       args->tls = 0;
>> +       args->tls = (uint64_t)tls_ptr;
>>
>>         parent_received_signal = 0;
>>         SAFE_SIGACTION(tc->exit_signal, &psig_action, NULL);
>> @@ -126,6 +151,7 @@ static void run(unsigned int n)
>>         TEST(pid = clone3(args, sizeof(*args)));
>>         if (pid < 0) {
>>                 tst_res(TFAIL | TTERRNO, "clone3() failed (%d)", n);
>> +               free(tls_ptr);
>>                 return;
>>         }
>>
>> @@ -139,11 +165,13 @@ static void run(unsigned int n)
>>                 TEST(pidfd_send_signal(pidfd, CHILD_SIGNAL, &uinfo, 0));
>>                 if (TST_RET != 0) {
>>                         tst_res(TFAIL | TTERRNO, "pidfd_send_signal()
>> failed");
>> +                       free(tls_ptr);
>>                         return;
>>                 }
>>         }
>>
>>         SAFE_WAITPID(pid, &status, __WALL);
>> +       free(tls_ptr);
>>
>>         if (!parent_received_signal) {
>>                 tst_res(TFAIL, "Parent haven't got signal");
>> --
>> 2.43.5
>>
>>
>> --
>> Mailing list info: https://lists.linux.it/listinfo/ltp
>>
>>
>
> --
> Regards,
> Li Wang
>
diff mbox series

Patch

diff --git a/testcases/kernel/syscalls/clone/clone08.c b/testcases/kernel/syscalls/clone/clone08.c
index dd97f3ff1..f5a8119a8 100644
--- a/testcases/kernel/syscalls/clone/clone08.c
+++ b/testcases/kernel/syscalls/clone/clone08.c
@@ -17,7 +17,11 @@ 
 #include "lapi/syscalls.h"
 #include "lapi/futex.h"
 
+#define TLS_SIZE 4096
+#define TLS_ALIGN 16
+
 static pid_t ptid, ctid, tgid;
+static void *tls_ptr;
 static void *child_stack;
 
 static void test_clone_parent(int t);
@@ -32,6 +36,9 @@  static int child_clone_parent_settid(void *);
 static void test_clone_thread(int t);
 static int child_clone_thread(void *);
 
+/* TLS variable to validate in child */
+static __thread int tls_test_var = 12345;
+
 /*
  * Children cloned with CLONE_VM should avoid using any functions that
  * might require dl_runtime_resolve, because they share thread-local
@@ -46,14 +53,14 @@  static struct test_case {
 	void (*testfunc)(int);
 	int (*do_child)(void *);
 } test_cases[] = {
-	{"CLONE_PARENT", CLONE_PARENT | SIGCHLD,
+	{"CLONE_PARENT", CLONE_PARENT | CLONE_SETTLS | SIGCHLD,
 	 test_clone_parent, child_clone_parent},
-	{"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD,
+	{"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | CLONE_SETTLS | SIGCHLD,
 	 test_clone_tid, child_clone_child_settid},
-	{"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | SIGCHLD,
+	{"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | CLONE_SETTLS | SIGCHLD,
 	 test_clone_tid, child_clone_parent_settid},
 	{"CLONE_THREAD", CLONE_THREAD | CLONE_SIGHAND | CLONE_VM |
-	 CLONE_CHILD_CLEARTID | SIGCHLD,
+	 CLONE_CHILD_CLEARTID | CLONE_SETTLS | SIGCHLD,
 	 test_clone_thread, child_clone_thread},
 };
 
@@ -66,17 +73,24 @@  static void do_test(unsigned int i)
 static void setup(void)
 {
 	child_stack = SAFE_MALLOC(CHILD_STACK_SIZE);
+	tls_ptr = aligned_alloc(TLS_ALIGN, TLS_SIZE);
+	if (!tls_ptr) {
+		perror("aligned_alloc");
+		exit(EXIT_FAILURE);
+	}
+	memset(tls_ptr, 0, TLS_SIZE);
 }
 
 static void cleanup(void)
 {
 	free(child_stack);
+	free(tls_ptr);
 }
 
 static long clone_child(const struct test_case *t)
 {
 	TEST(ltp_clone7(t->flags, t->do_child, NULL, CHILD_STACK_SIZE,
-		child_stack, &ptid, NULL, &ctid));
+		child_stack, &ptid, tls_ptr, &ctid));
 
 	if (TST_RET == -1 && TTERRNO == ENOSYS)
 		tst_brk(TCONF, "clone does not support 7 args");
@@ -87,6 +101,14 @@  static long clone_child(const struct test_case *t)
 	return TST_RET;
 }
 
+static void validate_tls(void)
+{
+	if (tls_test_var == 12345)
+		tst_res(TPASS, "Child TLS variable has expected value");
+	else
+		tst_res(TFAIL, "Child TLS variable corrupted or not set");
+}
+
 static void test_clone_parent(int t)
 {
 	pid_t child;
@@ -102,6 +124,8 @@  static void test_clone_parent(int t)
 
 static int child_clone_parent(void *arg LTP_ATTRIBUTE_UNUSED)
 {
+	validate_tls();
+
 	if (parent_ppid == getppid()) {
 		tst_res(TPASS, "clone and forked child has the same parent");
 	} else {
@@ -120,6 +144,8 @@  static void test_clone_tid(int t)
 
 static int child_clone_child_settid(void *arg LTP_ATTRIBUTE_UNUSED)
 {
+	validate_tls();
+
 	if (ctid == tst_syscall(__NR_getpid))
 		tst_res(TPASS, "clone() correctly set ctid");
 	else
@@ -130,6 +156,8 @@  static int child_clone_child_settid(void *arg LTP_ATTRIBUTE_UNUSED)
 
 static int child_clone_parent_settid(void *arg LTP_ATTRIBUTE_UNUSED)
 {
+	validate_tls();
+
 	if (ptid == tst_syscall(__NR_getpid))
 		tst_res(TPASS, "clone() correctly set ptid");
 	else
@@ -175,6 +203,8 @@  static void test_clone_thread(int t)
 
 static int child_clone_thread(void *arg LTP_ATTRIBUTE_UNUSED)
 {
+	validate_tls();
+
 	if (tgid == tst_syscall(__NR_getpid))
 		tst_res(TPASS, "clone has the same thread id");
 	else
diff --git a/testcases/kernel/syscalls/clone3/clone301.c b/testcases/kernel/syscalls/clone3/clone301.c
index deed30b9f..9571c9f5c 100644
--- a/testcases/kernel/syscalls/clone3/clone301.c
+++ b/testcases/kernel/syscalls/clone3/clone301.c
@@ -18,22 +18,38 @@ 
 
 #define CHILD_SIGNAL	SIGUSR1
 #define DATA	777
+#define TLS_SIZE 4096
+#define TLS_ALIGN 16
 
 static int pidfd, child_tid, parent_tid, parent_received_signal;
 static volatile int child_received_signal, child_data;
 static struct clone_args *args;
 
+/* TLS variable to validate in child */
+static __thread int tls_test_var = 12345;
+
 static struct tcase {
 	uint64_t flags;
 	int exit_signal;
 } tcases[] = {
 	{0, SIGCHLD},
 	{0, SIGUSR2},
-	{CLONE_FS, SIGCHLD},
-	{CLONE_NEWPID, SIGCHLD},
-	{CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_PIDFD, SIGCHLD},
+	{CLONE_FS | CLONE_SETTLS, SIGCHLD},
+	{CLONE_NEWPID | CLONE_SETTLS, SIGCHLD},
+	{CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_PIDFD | CLONE_SETTLS, SIGCHLD},
 };
 
+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 parent_rx_signal(int sig)
 {
 	parent_received_signal = sig;
@@ -67,6 +83,13 @@  static void do_child(int clone_pidfd)
 {
 	int count = 1000;
 
+	/* Validate TLS usage */
+	if (tls_test_var == 12345) {
+		tst_res(TPASS, "Child TLS variable has expected value");
+	} else {
+		tst_res(TFAIL, "Child TLS variable corrupted or not set");
+	}
+
 	if (clone_pidfd) {
 		child_received_signal = 0;
 		child_data = 0;
@@ -111,6 +134,8 @@  static void run(unsigned int n)
 	int status, clone_pidfd = tc->flags & CLONE_PIDFD;
 	pid_t pid;
 
+	void *tls_ptr = allocate_tls_region();
+
 	args->flags = tc->flags;
 	args->pidfd = (uint64_t)(&pidfd);
 	args->child_tid = (uint64_t)(&child_tid);
@@ -118,7 +143,7 @@  static void run(unsigned int n)
 	args->exit_signal = tc->exit_signal;
 	args->stack = 0;
 	args->stack_size = 0;
-	args->tls = 0;
+	args->tls = (uint64_t)tls_ptr;
 
 	parent_received_signal = 0;
 	SAFE_SIGACTION(tc->exit_signal, &psig_action, NULL);
@@ -126,6 +151,7 @@  static void run(unsigned int n)
 	TEST(pid = clone3(args, sizeof(*args)));
 	if (pid < 0) {
 		tst_res(TFAIL | TTERRNO, "clone3() failed (%d)", n);
+		free(tls_ptr);
 		return;
 	}
 
@@ -139,11 +165,13 @@  static void run(unsigned int n)
 		TEST(pidfd_send_signal(pidfd, CHILD_SIGNAL, &uinfo, 0));
 		if (TST_RET != 0) {
 			tst_res(TFAIL | TTERRNO, "pidfd_send_signal() failed");
+			free(tls_ptr);
 			return;
 		}
 	}
 
 	SAFE_WAITPID(pid, &status, __WALL);
+	free(tls_ptr);
 
 	if (!parent_received_signal) {
 		tst_res(TFAIL, "Parent haven't got signal");