diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-23 23:32:21 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-25 09:41:10 -0400 |
commit | 008f17948725c112a3422f72ed57fdc980e146a8 (patch) | |
tree | 0346d52f24b01c111835055b35d82f0ba8370bbf /arch/tile/kernel/process.c | |
parent | 6b14e4198c729b748a7f6d22059e6a101d2b241a (diff) |
tile: sanitize copy_thread()
Acked-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/tile/kernel/process.c')
-rw-r--r-- | arch/tile/kernel/process.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 6e7fb4e41f1c..1c20029d2f5a 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
@@ -158,7 +158,7 @@ static void save_arch_state(struct thread_struct *t); | |||
158 | 158 | ||
159 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 159 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
160 | unsigned long arg, | 160 | unsigned long arg, |
161 | struct task_struct *p, struct pt_regs *regs) | 161 | struct task_struct *p, struct pt_regs *unused) |
162 | { | 162 | { |
163 | struct pt_regs *childregs = task_pt_regs(p); | 163 | struct pt_regs *childregs = task_pt_regs(p); |
164 | unsigned long ksp; | 164 | unsigned long ksp; |
@@ -184,7 +184,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
184 | /* Record the pid of the task that created this one. */ | 184 | /* Record the pid of the task that created this one. */ |
185 | p->thread.creator_pid = current->pid; | 185 | p->thread.creator_pid = current->pid; |
186 | 186 | ||
187 | if (unlikely(!regs)) { | 187 | if (unlikely(p->flags & PF_KTHREAD)) { |
188 | /* kernel thread */ | 188 | /* kernel thread */ |
189 | memset(childregs, 0, sizeof(struct pt_regs)); | 189 | memset(childregs, 0, sizeof(struct pt_regs)); |
190 | memset(&callee_regs[2], 0, | 190 | memset(&callee_regs[2], 0, |
@@ -208,25 +208,26 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
208 | */ | 208 | */ |
209 | task_thread_info(p)->step_state = NULL; | 209 | task_thread_info(p)->step_state = NULL; |
210 | 210 | ||
211 | /* Save user stack top pointer so we can ID the stack vm area later. */ | ||
212 | p->thread.usp0 = sp; | ||
213 | |||
214 | /* | 211 | /* |
215 | * Copy the registers onto the kernel stack so the | 212 | * Copy the registers onto the kernel stack so the |
216 | * return-from-interrupt code will reload it into registers. | 213 | * return-from-interrupt code will reload it into registers. |
217 | */ | 214 | */ |
218 | *childregs = *regs; | 215 | *childregs = *current_pt_regs(); |
219 | childregs->regs[0] = 0; /* return value is zero */ | 216 | childregs->regs[0] = 0; /* return value is zero */ |
220 | childregs->sp = sp; /* override with new user stack pointer */ | 217 | if (sp) |
221 | memcpy(callee_regs, ®s->regs[CALLEE_SAVED_FIRST_REG], | 218 | childregs->sp = sp; /* override with new user stack pointer */ |
219 | memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG], | ||
222 | CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); | 220 | CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); |
223 | 221 | ||
222 | /* Save user stack top pointer so we can ID the stack vm area later. */ | ||
223 | p->thread.usp0 = childregs->sp; | ||
224 | |||
224 | /* | 225 | /* |
225 | * If CLONE_SETTLS is set, set "tp" in the new task to "r4", | 226 | * If CLONE_SETTLS is set, set "tp" in the new task to "r4", |
226 | * which is passed in as arg #5 to sys_clone(). | 227 | * which is passed in as arg #5 to sys_clone(). |
227 | */ | 228 | */ |
228 | if (clone_flags & CLONE_SETTLS) | 229 | if (clone_flags & CLONE_SETTLS) |
229 | childregs->tp = regs->regs[4]; | 230 | childregs->tp = childregs->regs[4]; |
230 | 231 | ||
231 | 232 | ||
232 | #if CHIP_HAS_TILE_DMA() | 233 | #if CHIP_HAS_TILE_DMA() |
@@ -587,10 +588,7 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) | |||
587 | SYSCALL_DEFINE4(clone, unsigned long, clone_flags, unsigned long, newsp, | 588 | SYSCALL_DEFINE4(clone, unsigned long, clone_flags, unsigned long, newsp, |
588 | void __user *, parent_tidptr, void __user *, child_tidptr) | 589 | void __user *, parent_tidptr, void __user *, child_tidptr) |
589 | { | 590 | { |
590 | struct pt_regs *regs = current_pt_regs(); | 591 | return do_fork(clone_flags, newsp, current_pt_regs(), 0, |
591 | if (!newsp) | ||
592 | newsp = regs->sp; | ||
593 | return do_fork(clone_flags, newsp, regs, 0, | ||
594 | parent_tidptr, child_tidptr); | 592 | parent_tidptr, child_tidptr); |
595 | } | 593 | } |
596 | 594 | ||