Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+45 -32
+1
arch/arm/Kconfig
··· 72 72 select HAVE_ARM_SMCCC if CPU_V7 73 73 select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32 74 74 select HAVE_CONTEXT_TRACKING 75 + select HAVE_COPY_THREAD_TLS 75 76 select HAVE_C_RECORDMCOUNT 76 77 select HAVE_DEBUG_KMEMLEAK 77 78 select HAVE_DMA_CONTIGUOUS if MMU
+3 -3
arch/arm/kernel/process.c
··· 226 226 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 227 227 228 228 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) 231 231 { 232 232 struct thread_info *thread = task_thread_info(p); 233 233 struct pt_regs *childregs = task_pt_regs(p); ··· 261 261 clear_ptrace_hw_breakpoint(p); 262 262 263 263 if (clone_flags & CLONE_SETTLS) 264 - thread->tp_value[0] = childregs->ARM_r3; 264 + thread->tp_value[0] = tls; 265 265 thread->tp_value[1] = get_tpuser(); 266 266 267 267 thread_notify(THREAD_NOTIFY_COPY, thread);
+1
arch/arm64/Kconfig
··· 138 138 select HAVE_CMPXCHG_DOUBLE 139 139 select HAVE_CMPXCHG_LOCAL 140 140 select HAVE_CONTEXT_TRACKING 141 + select HAVE_COPY_THREAD_TLS 141 142 select HAVE_DEBUG_BUGVERBOSE 142 143 select HAVE_DEBUG_KMEMLEAK 143 144 select HAVE_DMA_CONTIGUOUS
-1
arch/arm64/include/asm/unistd.h
··· 42 42 #endif 43 43 44 44 #define __ARCH_WANT_SYS_CLONE 45 - #define __ARCH_WANT_SYS_CLONE3 46 45 47 46 #ifndef __COMPAT_SYSCALL_NR 48 47 #include <uapi/asm/unistd.h>
+1
arch/arm64/include/uapi/asm/unistd.h
··· 19 19 #define __ARCH_WANT_NEW_STAT 20 20 #define __ARCH_WANT_SET_GET_RLIMIT 21 21 #define __ARCH_WANT_TIME32_SYSCALLS 22 + #define __ARCH_WANT_SYS_CLONE3 22 23 23 24 #include <asm-generic/unistd.h>
+5 -5
arch/arm64/kernel/process.c
··· 360 360 361 361 asmlinkage void ret_from_fork(void) asm("ret_from_fork"); 362 362 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) 365 365 { 366 366 struct pt_regs *childregs = task_pt_regs(p); 367 367 ··· 394 394 } 395 395 396 396 /* 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. 399 399 */ 400 400 if (clone_flags & CLONE_SETTLS) 401 - p->thread.uw.tp_value = childregs->regs[3]; 401 + p->thread.uw.tp_value = tls; 402 402 } else { 403 403 memset(childregs, 0, sizeof(struct pt_regs)); 404 404 childregs->pstate = PSR_MODE_EL1h;
+1
arch/parisc/Kconfig
··· 62 62 select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE 63 63 select HAVE_KPROBES_ON_FTRACE 64 64 select HAVE_DYNAMIC_FTRACE_WITH_REGS 65 + select HAVE_COPY_THREAD_TLS 65 66 66 67 help 67 68 The PA-RISC microprocessor is designed by Hewlett-Packard and used
+4 -4
arch/parisc/kernel/process.c
··· 208 208 * Copy architecture-specific thread state 209 209 */ 210 210 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) 213 213 { 214 214 struct pt_regs *cregs = &(p->thread.regs); 215 215 void *stack = task_stack_page(p); ··· 254 254 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; 255 255 cregs->kpc = (unsigned long) &child_return; 256 256 257 - /* Setup thread TLS area from the 4th parameter in clone */ 257 + /* Setup thread TLS area */ 258 258 if (clone_flags & CLONE_SETTLS) 259 - cregs->cr27 = cregs->gr[23]; 259 + cregs->cr27 = tls; 260 260 } 261 261 262 262 return 0;
+1
arch/riscv/Kconfig
··· 65 65 select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU 66 66 select HAVE_ARCH_MMAP_RND_BITS if MMU 67 67 select ARCH_HAS_GCOV_PROFILE_ALL 68 + select HAVE_COPY_THREAD_TLS 68 69 69 70 config ARCH_MMAP_RND_BITS_MIN 70 71 default 18 if 64BIT
+3 -3
arch/riscv/kernel/process.c
··· 99 99 return 0; 100 100 } 101 101 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) 104 104 { 105 105 struct pt_regs *childregs = task_pt_regs(p); 106 106 ··· 121 121 if (usp) /* User fork */ 122 122 childregs->sp = usp; 123 123 if (clone_flags & CLONE_SETTLS) 124 - childregs->tp = childregs->a5; 124 + childregs->tp = tls; 125 125 childregs->a0 = 0; /* Return value of fork() */ 126 126 p->thread.ra = (unsigned long)ret_from_fork; 127 127 }
+1
arch/um/Kconfig
··· 14 14 select HAVE_FUTEX_CMPXCHG if FUTEX 15 15 select HAVE_DEBUG_KMEMLEAK 16 16 select HAVE_DEBUG_BUGVERBOSE 17 + select HAVE_COPY_THREAD_TLS 17 18 select GENERIC_IRQ_SHOW 18 19 select GENERIC_CPU_DEVICES 19 20 select GENERIC_CLOCKEVENTS
+1 -1
arch/um/include/asm/ptrace-generic.h
··· 36 36 extern unsigned long getreg(struct task_struct *child, int regno); 37 37 extern int putreg(struct task_struct *child, int regno, unsigned long value); 38 38 39 - extern int arch_copy_tls(struct task_struct *new); 39 + extern int arch_set_tls(struct task_struct *new, unsigned long tls); 40 40 extern void clear_flushed_tls(struct task_struct *task); 41 41 extern int syscall_trace_enter(struct pt_regs *regs); 42 42 extern void syscall_trace_leave(struct pt_regs *regs);
+3 -3
arch/um/kernel/process.c
··· 153 153 userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs); 154 154 } 155 155 156 - int copy_thread(unsigned long clone_flags, unsigned long sp, 157 - unsigned long arg, struct task_struct * p) 156 + int copy_thread_tls(unsigned long clone_flags, unsigned long sp, 157 + unsigned long arg, struct task_struct * p, unsigned long tls) 158 158 { 159 159 void (*handler)(void); 160 160 int kthread = current->flags & PF_KTHREAD; ··· 188 188 * Set a new TLS for the child thread? 189 189 */ 190 190 if (clone_flags & CLONE_SETTLS) 191 - ret = arch_copy_tls(p); 191 + ret = arch_set_tls(p, tls); 192 192 } 193 193 194 194 return ret;
+2 -4
arch/x86/um/tls_32.c
··· 215 215 return 0; 216 216 } 217 217 218 - int arch_copy_tls(struct task_struct *new) 218 + int arch_set_tls(struct task_struct *new, unsigned long tls) 219 219 { 220 220 struct user_desc info; 221 221 int idx, ret = -EFAULT; 222 222 223 - if (copy_from_user(&info, 224 - (void __user *) UPT_SI(&new->thread.regs.regs), 225 - sizeof(info))) 223 + if (copy_from_user(&info, (void __user *) tls, sizeof(info))) 226 224 goto out; 227 225 228 226 ret = -EINVAL;
+3 -4
arch/x86/um/tls_64.c
··· 6 6 { 7 7 } 8 8 9 - int arch_copy_tls(struct task_struct *t) 9 + int arch_set_tls(struct task_struct *t, unsigned long tls) 10 10 { 11 11 /* 12 12 * If CLONE_SETTLS is set, we need to save the thread id 13 - * (which is argument 5, child_tid, of clone) so it can be set 14 - * during context switches. 13 + * so it can be set during context switches. 15 14 */ 16 - t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)]; 15 + t->thread.arch.fs = tls; 17 16 18 17 return 0; 19 18 }
+1
arch/xtensa/Kconfig
··· 24 24 select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL 25 25 select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL 26 26 select HAVE_ARCH_TRACEHOOK 27 + select HAVE_COPY_THREAD_TLS 27 28 select HAVE_DEBUG_KMEMLEAK 28 29 select HAVE_DMA_CONTIGUOUS 29 30 select HAVE_EXIT_THREAD
+4 -4
arch/xtensa/kernel/process.c
··· 202 202 * involved. Much simpler to just not copy those live frames across. 203 203 */ 204 204 205 - int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, 206 - unsigned long thread_fn_arg, struct task_struct *p) 205 + int copy_thread_tls(unsigned long clone_flags, unsigned long usp_thread_fn, 206 + unsigned long thread_fn_arg, struct task_struct *p, 207 + unsigned long tls) 207 208 { 208 209 struct pt_regs *childregs = task_pt_regs(p); 209 210 ··· 267 266 268 267 childregs->syscall = regs->syscall; 269 268 270 - /* The thread pointer is passed in the '4th argument' (= a5) */ 271 269 if (clone_flags & CLONE_SETTLS) 272 - childregs->threadptr = childregs->areg[5]; 270 + childregs->threadptr = tls; 273 271 } else { 274 272 p->thread.ra = MAKE_RA_FOR_CALL( 275 273 (unsigned long)ret_from_kernel_thread, 1);
+10
kernel/fork.c
··· 2578 2578 #endif 2579 2579 2580 2580 #ifdef __ARCH_WANT_SYS_CLONE3 2581 + 2582 + /* 2583 + * copy_thread implementations handle CLONE_SETTLS by reading the TLS value from 2584 + * the registers containing the syscall arguments for clone. This doesn't work 2585 + * with clone3 since the TLS value is passed in clone_args instead. 2586 + */ 2587 + #ifndef CONFIG_HAVE_COPY_THREAD_TLS 2588 + #error clone3 requires copy_thread_tls support in arch 2589 + #endif 2590 + 2581 2591 noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, 2582 2592 struct clone_args __user *uargs, 2583 2593 size_t usize)