Skip to content

Commit 088c484

Browse files
committed
lapi/tls: remove the TLS support from i386
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> Reviewed-by: Wei Gao <wegao@suse.com> Acked-by: Cyril Hrubis <chrubis@suse.cz>
1 parent bb05028 commit 088c484

1 file changed

Lines changed: 0 additions & 26 deletions

File tree

include/lapi/tls.h

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@
1717
#include <stdio.h>
1818
#include <unistd.h>
1919

20-
#if defined(__i386__)
21-
#include <asm/ldt.h>
22-
#endif
23-
2420
#include "tst_test.h"
2521

2622
#define TLS_SIZE 4096
@@ -37,7 +33,6 @@ typedef struct {
3733
#endif
3834

3935
extern void *tls_ptr;
40-
extern struct user_desc *tls_desc;
4136

4237
static inline void *allocate_tls_area(void)
4338
{
@@ -59,21 +54,6 @@ static inline void init_tls(void)
5954
{
6055
#if defined(__x86_64__) || defined(__aarch64__) || defined(__s390x__)
6156
tls_ptr = allocate_tls_area();
62-
63-
#elif defined(__i386__)
64-
tls_ptr = allocate_tls_area();
65-
tls_desc = SAFE_MALLOC(sizeof(*tls_desc));
66-
memset(tls_desc, 0, sizeof(*tls_desc));
67-
tls_desc->entry_number = -1;
68-
tls_desc->base_addr = (unsigned long)tls_ptr;
69-
tls_desc->limit = TLS_SIZE;
70-
tls_desc->seg_32bit = 1;
71-
tls_desc->contents = 0;
72-
tls_desc->read_exec_only = 0;
73-
tls_desc->limit_in_pages = 0;
74-
tls_desc->seg_not_present = 0;
75-
tls_desc->useable = 1;
76-
7757
#else
7858
tst_brk(TCONF, "Unsupported architecture for TLS");
7959
#endif
@@ -87,12 +67,6 @@ static inline void free_tls(void)
8767
free(tls_ptr);
8868
tls_ptr = NULL;
8969
}
90-
#elif defined(__i386__)
91-
if (tls_desc) {
92-
free((void *)(uintptr_t)tls_desc->base_addr);
93-
free(tls_desc);
94-
tls_desc = NULL;
95-
}
9670
#endif
9771
}
9872

0 commit comments

Comments
 (0)