* [LTP] [PATCH] lapi/tls: remove the TLS support from i386
@ 2026-01-21 9:01 Li Wang via ltp
2026-01-21 9:48 ` Wei Gao via ltp
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Li Wang via ltp @ 2026-01-21 9:01 UTC (permalink / raw)
To: ltp
Using a LTP naked clone() to verify that CLONE_SETTLS is unreliable
when running 32-bit on x86_64, since TLS requires two steps: writing
the descriptor and switching the selector. But CLONE_SETTLS on i386
only overrides the former:
kernel_clone()
copy_process()
copy_thread()
set_new_tls()
do_set_thread_area()
In copy_thread(), the child's register frame is copied from the parent
*childregs = *current_pt_regs(); and on the 32-bit side it also does
savesegment(gs, p->thread.gs); saving the current %gs into thread_struct.
Together, this means that unless something explicitly overwrites it later,
the child's initial %gs selector is inherited from the parent.
https://elixir.bootlin.com/linux/v6.18/source/arch/x86/kernel/process.c#L243
Then, in do_set_thread_area(), the kernel updates the TLS descriptor
set_tls_desc(p, idx, &info, 1); However, when (p != current), the x86_32 path
does not update or refresh any segment selector. So it updates the descriptor
but does not switch the child's %gs selector to the new modified_sel.
https://elixir.bootlin.com/linux/v6.18/source/arch/x86/kernel/tls.c#L150
Therefore, on i386, relying on CLONE_SETTLS alone can leave the child
executing with the parent's %gs selector, so TLS accesses still resolve
to the old TLS base.
===============
The behavior above explains why clone10 fails even if we update the TLS
descriptor base (either hard-coding or via set_thread_area()).
Example (x86_64 kernel running a 32-bit ELF):
# uname -rm
6.19.0-rc2.liwang x86_64
# readelf -h clone10 |grep Class
Class: ELF32
# ./clone10
...
clone10.c:48: TINFO: Child (PID: 5262, TID: 5263): TLS value set to: 101
clone10.c:72: TFAIL: Parent (PID: 5262, TID: 5262): TLS value mismatch: got 101, expected 100
Reported-by: Wei Gao <wegao@suse.com>
Signed-off-by: Li Wang <liwang@redhat.com>
---
include/lapi/tls.h | 26 --------------------------
1 file changed, 26 deletions(-)
diff --git a/include/lapi/tls.h b/include/lapi/tls.h
index a067872e0..f7e2f483f 100644
--- a/include/lapi/tls.h
+++ b/include/lapi/tls.h
@@ -17,10 +17,6 @@
#include <stdio.h>
#include <unistd.h>
-#if defined(__i386__)
-#include <asm/ldt.h>
-#endif
-
#include "tst_test.h"
#define TLS_SIZE 4096
@@ -37,7 +33,6 @@ typedef struct {
#endif
extern void *tls_ptr;
-extern struct user_desc *tls_desc;
static inline void *allocate_tls_area(void)
{
@@ -59,21 +54,6 @@ static inline 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
@@ -87,12 +67,6 @@ static inline void free_tls(void)
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
}
--
2.52.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] lapi/tls: remove the TLS support from i386
2026-01-21 9:01 [LTP] [PATCH] lapi/tls: remove the TLS support from i386 Li Wang via ltp
@ 2026-01-21 9:48 ` Wei Gao via ltp
2026-01-21 13:32 ` Cyril Hrubis
2026-01-22 10:41 ` Jan Stancek via ltp
2 siblings, 0 replies; 7+ messages in thread
From: Wei Gao via ltp @ 2026-01-21 9:48 UTC (permalink / raw)
To: Li Wang; +Cc: ltp
On Wed, Jan 21, 2026 at 05:01:59PM +0800, Li Wang wrote:
> Using a LTP naked clone() to verify that CLONE_SETTLS is unreliable
> when running 32-bit on x86_64, since TLS requires two steps: writing
> the descriptor and switching the selector. But CLONE_SETTLS on i386
> only overrides the former:
>
> kernel_clone()
> copy_process()
> copy_thread()
> set_new_tls()
> do_set_thread_area()
>
> In copy_thread(), the child's register frame is copied from the parent
> *childregs = *current_pt_regs(); and on the 32-bit side it also does
> savesegment(gs, p->thread.gs); saving the current %gs into thread_struct.
>
> Together, this means that unless something explicitly overwrites it later,
> the child's initial %gs selector is inherited from the parent.
>
> https://elixir.bootlin.com/linux/v6.18/source/arch/x86/kernel/process.c#L243
>
> Then, in do_set_thread_area(), the kernel updates the TLS descriptor
> set_tls_desc(p, idx, &info, 1); However, when (p != current), the x86_32 path
> does not update or refresh any segment selector. So it updates the descriptor
> but does not switch the child's %gs selector to the new modified_sel.
>
> https://elixir.bootlin.com/linux/v6.18/source/arch/x86/kernel/tls.c#L150
>
> Therefore, on i386, relying on CLONE_SETTLS alone can leave the child
> executing with the parent's %gs selector, so TLS accesses still resolve
> to the old TLS base.
>
> ===============
>
> The behavior above explains why clone10 fails even if we update the TLS
> descriptor base (either hard-coding or via set_thread_area()).
>
> Example (x86_64 kernel running a 32-bit ELF):
>
> # uname -rm
> 6.19.0-rc2.liwang x86_64
>
> # readelf -h clone10 |grep Class
> Class: ELF32
>
> # ./clone10
> ...
> clone10.c:48: TINFO: Child (PID: 5262, TID: 5263): TLS value set to: 101
> clone10.c:72: TFAIL: Parent (PID: 5262, TID: 5262): TLS value mismatch: got 101, expected 100
>
> Reported-by: Wei Gao <wegao@suse.com>
> Signed-off-by: Li Wang <liwang@redhat.com>
> ---
> include/lapi/tls.h | 26 --------------------------
> 1 file changed, 26 deletions(-)
>
> diff --git a/include/lapi/tls.h b/include/lapi/tls.h
> index a067872e0..f7e2f483f 100644
> --- a/include/lapi/tls.h
> +++ b/include/lapi/tls.h
> @@ -17,10 +17,6 @@
> #include <stdio.h>
> #include <unistd.h>
>
> -#if defined(__i386__)
> -#include <asm/ldt.h>
> -#endif
> -
> #include "tst_test.h"
>
> #define TLS_SIZE 4096
> @@ -37,7 +33,6 @@ typedef struct {
> #endif
>
> extern void *tls_ptr;
> -extern struct user_desc *tls_desc;
>
> static inline void *allocate_tls_area(void)
> {
> @@ -59,21 +54,6 @@ static inline 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
> @@ -87,12 +67,6 @@ static inline void free_tls(void)
> 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
> }
Thanks for your patch.
Reviewed-by: Wei Gao <wegao@suse.com>
>
> --
> 2.52.0
>
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] lapi/tls: remove the TLS support from i386
2026-01-21 9:01 [LTP] [PATCH] lapi/tls: remove the TLS support from i386 Li Wang via ltp
2026-01-21 9:48 ` Wei Gao via ltp
@ 2026-01-21 13:32 ` Cyril Hrubis
2026-01-22 0:39 ` Li Wang via ltp
2026-01-22 10:41 ` Jan Stancek via ltp
2 siblings, 1 reply; 7+ messages in thread
From: Cyril Hrubis @ 2026-01-21 13:32 UTC (permalink / raw)
To: Li Wang; +Cc: ltp
Hi!
Shouldn't we also set .supported_archs to x86_64 in clone10?
Otherwise:
Acked-by: Cyril Hrubis <chrubis@suse.cz>
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] lapi/tls: remove the TLS support from i386
2026-01-21 13:32 ` Cyril Hrubis
@ 2026-01-22 0:39 ` Li Wang via ltp
2026-01-22 10:20 ` Cyril Hrubis
0 siblings, 1 reply; 7+ messages in thread
From: Li Wang via ltp @ 2026-01-22 0:39 UTC (permalink / raw)
To: Cyril Hrubis; +Cc: ltp
> Shouldn't we also set .supported_archs to x86_64 in clone10?
Nope, the others archs also work (aarch64, s390x, etc).
> Otherwise:
>
> Acked-by: Cyril Hrubis <chrubis@suse.cz>
Merged, thanks!
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] lapi/tls: remove the TLS support from i386
2026-01-22 0:39 ` Li Wang via ltp
@ 2026-01-22 10:20 ` Cyril Hrubis
2026-01-22 10:27 ` Li Wang via ltp
0 siblings, 1 reply; 7+ messages in thread
From: Cyril Hrubis @ 2026-01-22 10:20 UTC (permalink / raw)
To: Li Wang; +Cc: ltp
Hi!
> > Shouldn't we also set .supported_archs to x86_64 in clone10?
>
> Nope, the others archs also work (aarch64, s390x, etc).
The the supported_archs should be set to:
{"x86_64", "s390x", "aarch64", NULL}
right?
The code would TCONF on any other architecture.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] lapi/tls: remove the TLS support from i386
2026-01-22 10:20 ` Cyril Hrubis
@ 2026-01-22 10:27 ` Li Wang via ltp
0 siblings, 0 replies; 7+ messages in thread
From: Li Wang via ltp @ 2026-01-22 10:27 UTC (permalink / raw)
To: Cyril Hrubis; +Cc: ltp
Cyril Hrubis <chrubis@suse.cz> wrote:
> > > Shouldn't we also set .supported_archs to x86_64 in clone10?
> >
> > Nope, the others archs also work (aarch64, s390x, etc).
>
> The the supported_archs should be set to:
>
> {"x86_64", "s390x", "aarch64", NULL}
>
> right?
Ah right, I have sent a new patch.
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] lapi/tls: remove the TLS support from i386
2026-01-21 9:01 [LTP] [PATCH] lapi/tls: remove the TLS support from i386 Li Wang via ltp
2026-01-21 9:48 ` Wei Gao via ltp
2026-01-21 13:32 ` Cyril Hrubis
@ 2026-01-22 10:41 ` Jan Stancek via ltp
2 siblings, 0 replies; 7+ messages in thread
From: Jan Stancek via ltp @ 2026-01-22 10:41 UTC (permalink / raw)
To: Li Wang; +Cc: ltp
On Wed, Jan 21, 2026 at 10:02 AM Li Wang via ltp <ltp@lists.linux.it> wrote:
>
> Using a LTP naked clone() to verify that CLONE_SETTLS is unreliable
> when running 32-bit on x86_64, since TLS requires two steps: writing
> the descriptor and switching the selector. But CLONE_SETTLS on i386
> only overrides the former:
>
> kernel_clone()
> copy_process()
> copy_thread()
> set_new_tls()
> do_set_thread_area()
>
> In copy_thread(), the child's register frame is copied from the parent
> *childregs = *current_pt_regs(); and on the 32-bit side it also does
> savesegment(gs, p->thread.gs); saving the current %gs into thread_struct.
>
> Together, this means that unless something explicitly overwrites it later,
> the child's initial %gs selector is inherited from the parent.
>
> https://elixir.bootlin.com/linux/v6.18/source/arch/x86/kernel/process.c#L243
>
> Then, in do_set_thread_area(), the kernel updates the TLS descriptor
> set_tls_desc(p, idx, &info, 1); However, when (p != current), the x86_32 path
> does not update or refresh any segment selector. So it updates the descriptor
> but does not switch the child's %gs selector to the new modified_sel.
>
> https://elixir.bootlin.com/linux/v6.18/source/arch/x86/kernel/tls.c#L150
>
> Therefore, on i386, relying on CLONE_SETTLS alone can leave the child
> executing with the parent's %gs selector, so TLS accesses still resolve
> to the old TLS base.
>
> ===============
>
> The behavior above explains why clone10 fails even if we update the TLS
> descriptor base (either hard-coding or via set_thread_area()).
>
> Example (x86_64 kernel running a 32-bit ELF):
>
> # uname -rm
> 6.19.0-rc2.liwang x86_64
>
> # readelf -h clone10 |grep Class
> Class: ELF32
>
> # ./clone10
> ...
> clone10.c:48: TINFO: Child (PID: 5262, TID: 5263): TLS value set to: 101
> clone10.c:72: TFAIL: Parent (PID: 5262, TID: 5262): TLS value mismatch: got 101, expected 100
>
> Reported-by: Wei Gao <wegao@suse.com>
> Signed-off-by: Li Wang <liwang@redhat.com>
Acked-by: Jan Stancek <jstancek@redhat.com>
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-01-22 10:42 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-21 9:01 [LTP] [PATCH] lapi/tls: remove the TLS support from i386 Li Wang via ltp
2026-01-21 9:48 ` Wei Gao via ltp
2026-01-21 13:32 ` Cyril Hrubis
2026-01-22 0:39 ` Li Wang via ltp
2026-01-22 10:20 ` Cyril Hrubis
2026-01-22 10:27 ` Li Wang via ltp
2026-01-22 10:41 ` Jan Stancek via ltp
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.