Commit 457677c7 authored by Amanieu d'Antras's avatar Amanieu d'Antras Committed by Christian Brauner

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: default avatarAmanieu 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.comSigned-off-by: default avatarChristian Brauner <christian.brauner@ubuntu.com>
parent dd499f7a
...@@ -14,6 +14,7 @@ config UML ...@@ -14,6 +14,7 @@ config UML
select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_FUTEX_CMPXCHG if FUTEX
select HAVE_DEBUG_KMEMLEAK select HAVE_DEBUG_KMEMLEAK
select HAVE_DEBUG_BUGVERBOSE select HAVE_DEBUG_BUGVERBOSE
select HAVE_COPY_THREAD_TLS
select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW
select GENERIC_CPU_DEVICES select GENERIC_CPU_DEVICES
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
......
...@@ -36,7 +36,7 @@ extern long subarch_ptrace(struct task_struct *child, long request, ...@@ -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 unsigned long getreg(struct task_struct *child, int regno);
extern int putreg(struct task_struct *child, int regno, unsigned long value); 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 void clear_flushed_tls(struct task_struct *task);
extern int syscall_trace_enter(struct pt_regs *regs); extern int syscall_trace_enter(struct pt_regs *regs);
extern void syscall_trace_leave(struct pt_regs *regs); extern void syscall_trace_leave(struct pt_regs *regs);
......
...@@ -153,8 +153,8 @@ void fork_handler(void) ...@@ -153,8 +153,8 @@ void fork_handler(void)
userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs); userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
} }
int copy_thread(unsigned long clone_flags, unsigned long sp, int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
unsigned long arg, struct task_struct * p) unsigned long arg, struct task_struct * p, unsigned long tls)
{ {
void (*handler)(void); void (*handler)(void);
int kthread = current->flags & PF_KTHREAD; int kthread = current->flags & PF_KTHREAD;
...@@ -188,7 +188,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, ...@@ -188,7 +188,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
* Set a new TLS for the child thread? * Set a new TLS for the child thread?
*/ */
if (clone_flags & CLONE_SETTLS) if (clone_flags & CLONE_SETTLS)
ret = arch_copy_tls(p); ret = arch_set_tls(p, tls);
} }
return ret; return ret;
......
...@@ -215,14 +215,12 @@ static int set_tls_entry(struct task_struct* task, struct user_desc *info, ...@@ -215,14 +215,12 @@ static int set_tls_entry(struct task_struct* task, struct user_desc *info,
return 0; 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; struct user_desc info;
int idx, ret = -EFAULT; int idx, ret = -EFAULT;
if (copy_from_user(&info, if (copy_from_user(&info, (void __user *) tls, sizeof(info)))
(void __user *) UPT_SI(&new->thread.regs.regs),
sizeof(info)))
goto out; goto out;
ret = -EINVAL; ret = -EINVAL;
......
...@@ -6,14 +6,13 @@ void clear_flushed_tls(struct task_struct *task) ...@@ -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 * 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 * so it can be set during context switches.
* during context switches.
*/ */
t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)]; t->thread.arch.fs = tls;
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment