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 |
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 |
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 > >
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 > >
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 --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");
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(-)