um: Implement copy_thread_tls

This is required for clone3 which passes the TLS value through a
struct rather than a register.

Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
Cc: linux-um@lists.infradead.org
Cc: <stable@vger.kernel.org> # 5.3.x
Link: https://lore.kernel.org/r/20200104123928.1048822-1-amanieu@gmail.com
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>

authored by Amanieu d'Antras and committed by Christian Brauner 457677c7 dd499f7a

Changed files
+10 -12
arch
um
include
kernel
x86
+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 }