OSDN Git Service

um: Implement copy_thread_tls
authorAmanieu d'Antras <amanieu@gmail.com>
Sat, 4 Jan 2020 12:39:30 +0000 (13:39 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 7 Jan 2020 12:31:29 +0000 (13:31 +0100)
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>
arch/um/Kconfig
arch/um/include/asm/ptrace-generic.h
arch/um/kernel/process.c
arch/x86/um/tls_32.c
arch/x86/um/tls_64.c

index 2a6d04f..6f0edd0 100644 (file)
@@ -14,6 +14,7 @@ config UML
        select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DEBUG_BUGVERBOSE
+       select HAVE_COPY_THREAD_TLS
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
        select GENERIC_CLOCKEVENTS
index 81c647e..adf91ef 100644 (file)
@@ -36,7 +36,7 @@ extern long subarch_ptrace(struct task_struct *child, long request,
 extern unsigned long getreg(struct task_struct *child, int regno);
 extern int putreg(struct task_struct *child, int regno, unsigned long value);
 
-extern int arch_copy_tls(struct task_struct *new);
+extern int arch_set_tls(struct task_struct *new, unsigned long tls);
 extern void clear_flushed_tls(struct task_struct *task);
 extern int syscall_trace_enter(struct pt_regs *regs);
 extern void syscall_trace_leave(struct pt_regs *regs);
index 263a8f0..17045e7 100644 (file)
@@ -153,8 +153,8 @@ void fork_handler(void)
        userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
 }
 
-int copy_thread(unsigned long clone_flags, unsigned long sp,
-               unsigned long arg, struct task_struct * p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
+               unsigned long arg, struct task_struct * p, unsigned long tls)
 {
        void (*handler)(void);
        int kthread = current->flags & PF_KTHREAD;
@@ -188,7 +188,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
                 * Set a new TLS for the child thread?
                 */
                if (clone_flags & CLONE_SETTLS)
-                       ret = arch_copy_tls(p);
+                       ret = arch_set_tls(p, tls);
        }
 
        return ret;
index 5bd949d..ac8eee0 100644 (file)
@@ -215,14 +215,12 @@ static int set_tls_entry(struct task_struct* task, struct user_desc *info,
        return 0;
 }
 
-int arch_copy_tls(struct task_struct *new)
+int arch_set_tls(struct task_struct *new, unsigned long tls)
 {
        struct user_desc info;
        int idx, ret = -EFAULT;
 
-       if (copy_from_user(&info,
-                          (void __user *) UPT_SI(&new->thread.regs.regs),
-                          sizeof(info)))
+       if (copy_from_user(&info, (void __user *) tls, sizeof(info)))
                goto out;
 
        ret = -EINVAL;
index 3a621e0..ebd3855 100644 (file)
@@ -6,14 +6,13 @@ void clear_flushed_tls(struct task_struct *task)
 {
 }
 
-int arch_copy_tls(struct task_struct *t)
+int arch_set_tls(struct task_struct *t, unsigned long tls)
 {
        /*
         * If CLONE_SETTLS is set, we need to save the thread id
-        * (which is argument 5, child_tid, of clone) so it can be set
-        * during context switches.
+        * so it can be set during context switches.
         */
-       t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
+       t->thread.arch.fs = tls;
 
        return 0;
 }