Skip to content

Commit 606e9ad

Browse files
committed
Merge tag 'clone3-tls-v5.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux
Pull thread fixes from Christian Brauner: "This contains a series of patches to fix CLONE_SETTLS when used with clone3(). The clone3() syscall passes the tls argument through struct clone_args instead of a register. This means, all architectures that do not implement copy_thread_tls() but still support CLONE_SETTLS via copy_thread() expecting the tls to be located in a register argument based on clone() are currently unfortunately broken. Their tls value will be garbage. The patch series fixes this on all architectures that currently define __ARCH_WANT_SYS_CLONE3. It also adds a compile-time check to ensure that any architecture that enables clone3() in the future is forced to also implement copy_thread_tls(). My ultimate goal is to get rid of the copy_thread()/copy_thread_tls() split and just have copy_thread_tls() at some point in the not too distant future (Maybe even renaming copy_thread_tls() back to simply copy_thread() once the old function is ripped from all arches). This is dependent now on all arches supporting clone3(). While all relevant arches do that now there are still four missing: ia64, m68k, sh and sparc. They have the system call reserved, but not implemented. Once they all implement clone3() we can get rid of ARCH_WANT_SYS_CLONE3 and HAVE_COPY_THREAD_TLS. This series also includes a minor fix for the arm64 uapi headers which caused __NR_clone3 to be missing from the exported user headers. Unfortunately the series came in a little late especially given that it touches a range of architectures. Due to the holidays not all arch maintainers responded in time probably due to their backlog. Will and Arnd have thankfully acked the arm specific changes. Given that the changes are straightforward and rather minimal combined with the fact the that clone3() with CLONE_SETTLS is broken I decided to send them post rc3 nonetheless" * tag 'clone3-tls-v5.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux: um: Implement copy_thread_tls clone3: ensure copy_thread_tls is implemented xtensa: Implement copy_thread_tls riscv: Implement copy_thread_tls parisc: Implement copy_thread_tls arm: Implement copy_thread_tls arm64: Implement copy_thread_tls arm64: Move __ARCH_WANT_SYS_CLONE3 definition to uapi headers
2 parents ac61145 + 457677c commit 606e9ad

File tree

18 files changed

+45
-32
lines changed

18 files changed

+45
-32
lines changed

arch/arm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ config ARM
7272
select HAVE_ARM_SMCCC if CPU_V7
7373
select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32
7474
select HAVE_CONTEXT_TRACKING
75+
select HAVE_COPY_THREAD_TLS
7576
select HAVE_C_RECORDMCOUNT
7677
select HAVE_DEBUG_KMEMLEAK
7778
select HAVE_DMA_CONTIGUOUS if MMU

arch/arm/kernel/process.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ void release_thread(struct task_struct *dead_task)
226226
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
227227

228228
int
229-
copy_thread(unsigned long clone_flags, unsigned long stack_start,
230-
unsigned long stk_sz, struct task_struct *p)
229+
copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
230+
unsigned long stk_sz, struct task_struct *p, unsigned long tls)
231231
{
232232
struct thread_info *thread = task_thread_info(p);
233233
struct pt_regs *childregs = task_pt_regs(p);
@@ -261,7 +261,7 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
261261
clear_ptrace_hw_breakpoint(p);
262262

263263
if (clone_flags & CLONE_SETTLS)
264-
thread->tp_value[0] = childregs->ARM_r3;
264+
thread->tp_value[0] = tls;
265265
thread->tp_value[1] = get_tpuser();
266266

267267
thread_notify(THREAD_NOTIFY_COPY, thread);

arch/arm64/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ config ARM64
138138
select HAVE_CMPXCHG_DOUBLE
139139
select HAVE_CMPXCHG_LOCAL
140140
select HAVE_CONTEXT_TRACKING
141+
select HAVE_COPY_THREAD_TLS
141142
select HAVE_DEBUG_BUGVERBOSE
142143
select HAVE_DEBUG_KMEMLEAK
143144
select HAVE_DMA_CONTIGUOUS

arch/arm64/include/asm/unistd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
#endif
4343

4444
#define __ARCH_WANT_SYS_CLONE
45-
#define __ARCH_WANT_SYS_CLONE3
4645

4746
#ifndef __COMPAT_SYSCALL_NR
4847
#include <uapi/asm/unistd.h>

arch/arm64/include/uapi/asm/unistd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
#define __ARCH_WANT_NEW_STAT
2020
#define __ARCH_WANT_SET_GET_RLIMIT
2121
#define __ARCH_WANT_TIME32_SYSCALLS
22+
#define __ARCH_WANT_SYS_CLONE3
2223

2324
#include <asm-generic/unistd.h>

arch/arm64/kernel/process.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
360360

361361
asmlinkage void ret_from_fork(void) asm("ret_from_fork");
362362

363-
int copy_thread(unsigned long clone_flags, unsigned long stack_start,
364-
unsigned long stk_sz, struct task_struct *p)
363+
int copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
364+
unsigned long stk_sz, struct task_struct *p, unsigned long tls)
365365
{
366366
struct pt_regs *childregs = task_pt_regs(p);
367367

@@ -394,11 +394,11 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
394394
}
395395

396396
/*
397-
* If a TLS pointer was passed to clone (4th argument), use it
398-
* for the new thread.
397+
* If a TLS pointer was passed to clone, use it for the new
398+
* thread.
399399
*/
400400
if (clone_flags & CLONE_SETTLS)
401-
p->thread.uw.tp_value = childregs->regs[3];
401+
p->thread.uw.tp_value = tls;
402402
} else {
403403
memset(childregs, 0, sizeof(struct pt_regs));
404404
childregs->pstate = PSR_MODE_EL1h;

arch/parisc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ config PARISC
6262
select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE
6363
select HAVE_KPROBES_ON_FTRACE
6464
select HAVE_DYNAMIC_FTRACE_WITH_REGS
65+
select HAVE_COPY_THREAD_TLS
6566

6667
help
6768
The PA-RISC microprocessor is designed by Hewlett-Packard and used

arch/parisc/kernel/process.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@ arch_initcall(parisc_idle_init);
208208
* Copy architecture-specific thread state
209209
*/
210210
int
211-
copy_thread(unsigned long clone_flags, unsigned long usp,
212-
unsigned long kthread_arg, struct task_struct *p)
211+
copy_thread_tls(unsigned long clone_flags, unsigned long usp,
212+
unsigned long kthread_arg, struct task_struct *p, unsigned long tls)
213213
{
214214
struct pt_regs *cregs = &(p->thread.regs);
215215
void *stack = task_stack_page(p);
@@ -254,9 +254,9 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
254254
cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
255255
cregs->kpc = (unsigned long) &child_return;
256256

257-
/* Setup thread TLS area from the 4th parameter in clone */
257+
/* Setup thread TLS area */
258258
if (clone_flags & CLONE_SETTLS)
259-
cregs->cr27 = cregs->gr[23];
259+
cregs->cr27 = tls;
260260
}
261261

262262
return 0;

arch/riscv/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ config RISCV
6565
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
6666
select HAVE_ARCH_MMAP_RND_BITS if MMU
6767
select ARCH_HAS_GCOV_PROFILE_ALL
68+
select HAVE_COPY_THREAD_TLS
6869

6970
config ARCH_MMAP_RND_BITS_MIN
7071
default 18 if 64BIT

arch/riscv/kernel/process.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
9999
return 0;
100100
}
101101

102-
int copy_thread(unsigned long clone_flags, unsigned long usp,
103-
unsigned long arg, struct task_struct *p)
102+
int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
103+
unsigned long arg, struct task_struct *p, unsigned long tls)
104104
{
105105
struct pt_regs *childregs = task_pt_regs(p);
106106

@@ -121,7 +121,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
121121
if (usp) /* User fork */
122122
childregs->sp = usp;
123123
if (clone_flags & CLONE_SETTLS)
124-
childregs->tp = childregs->a5;
124+
childregs->tp = tls;
125125
childregs->a0 = 0; /* Return value of fork() */
126126
p->thread.ra = (unsigned long)ret_from_fork;
127127
}

0 commit comments

Comments
 (0)