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>
This commit is contained in:
		
				
					committed by
					
						 Christian Brauner
						Christian Brauner
					
				
			
			
				
	
			
			
			
						parent
						
							dd499f7a7e
						
					
				
				
					commit
					457677c70c
				
			| @@ -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 | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -153,8 +153,8 @@ void fork_handler(void) | ||||
| 	userspace(¤t->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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user