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

x86: opt into HAVE_COPY_THREAD_TLS, for both 32-bit and 64-bit

For 32-bit userspace on a 64-bit kernel, this requires modifying
stub32_clone to actually swap the appropriate arguments to match
CONFIG_CLONE_BACKWARDS, rather than just leaving the C argument for tls
broken.

Patch co-authored by Josh Triplett and Thiago Macieira.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Acked-by: Andy Lutomirski <luto@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Thiago Macieira <thiago.macieira@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Josh Triplett and committed by
Linus Torvalds
c1bd55f9 20263029

+8 -7
+1
arch/x86/Kconfig
··· 88 88 select HAVE_CMPXCHG_DOUBLE 89 89 select HAVE_CMPXCHG_LOCAL 90 90 select HAVE_CONTEXT_TRACKING if X86_64 91 + select HAVE_COPY_THREAD_TLS 91 92 select HAVE_C_RECORDMCOUNT 92 93 select HAVE_DEBUG_KMEMLEAK 93 94 select HAVE_DEBUG_STACKOVERFLOW
+3 -3
arch/x86/kernel/process_32.c
··· 128 128 release_vm86_irqs(dead_task); 129 129 } 130 130 131 - int copy_thread(unsigned long clone_flags, unsigned long sp, 132 - unsigned long arg, struct task_struct *p) 131 + int copy_thread_tls(unsigned long clone_flags, unsigned long sp, 132 + unsigned long arg, struct task_struct *p, unsigned long tls) 133 133 { 134 134 struct pt_regs *childregs = task_pt_regs(p); 135 135 struct task_struct *tsk; ··· 184 184 */ 185 185 if (clone_flags & CLONE_SETTLS) 186 186 err = do_set_thread_area(p, -1, 187 - (struct user_desc __user *)childregs->si, 0); 187 + (struct user_desc __user *)tls, 0); 188 188 189 189 if (err && p->thread.io_bitmap_ptr) { 190 190 kfree(p->thread.io_bitmap_ptr);
+4 -4
arch/x86/kernel/process_64.c
··· 150 150 return get_desc_base(&t->thread.tls_array[tls]); 151 151 } 152 152 153 - int copy_thread(unsigned long clone_flags, unsigned long sp, 154 - unsigned long arg, struct task_struct *p) 153 + int copy_thread_tls(unsigned long clone_flags, unsigned long sp, 154 + unsigned long arg, struct task_struct *p, unsigned long tls) 155 155 { 156 156 int err; 157 157 struct pt_regs *childregs; ··· 207 207 #ifdef CONFIG_IA32_EMULATION 208 208 if (is_ia32_task()) 209 209 err = do_set_thread_area(p, -1, 210 - (struct user_desc __user *)childregs->si, 0); 210 + (struct user_desc __user *)tls, 0); 211 211 else 212 212 #endif 213 - err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); 213 + err = do_arch_prctl(p, ARCH_SET_FS, tls); 214 214 if (err) 215 215 goto out; 216 216 }