fork: clone_thread: free resources when an error is detected
Change-Id: I922f3fddc35942ef2c67db6673980770731dced9
This commit is contained in:
committed by
Masamichi Takagi
parent
3e9fdfc0f1
commit
bb08742467
@ -832,6 +832,7 @@ void hold_process_vm(struct process_vm *vm);
|
||||
void release_process_vm(struct process_vm *vm);
|
||||
void hold_process(struct process *);
|
||||
void release_process(struct process *);
|
||||
void free_all_process_memory_range(struct process_vm *vm);
|
||||
void free_process_memory_ranges(struct process_vm *vm);
|
||||
int populate_process_memory(struct process_vm *vm, void *start, size_t len);
|
||||
|
||||
|
||||
@ -84,6 +84,7 @@ extern void procfs_delete_thread(struct thread *);
|
||||
|
||||
static int free_process_memory_range(struct process_vm *vm,
|
||||
struct vm_range *range);
|
||||
static void free_thread_pages(struct thread *thread);
|
||||
|
||||
struct list_head resource_set_list;
|
||||
mcs_rwlock_lock_t resource_set_lock;
|
||||
@ -407,8 +408,12 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
||||
KERNEL_STACK_NR_PAGES * PAGE_SIZE, pc, sp);
|
||||
|
||||
/* copy fp_regs from parent */
|
||||
save_fp_regs(org);
|
||||
copy_fp_regs(org, thread);
|
||||
if (save_fp_regs(org)) {
|
||||
goto free_thread;
|
||||
}
|
||||
if (copy_fp_regs(org, thread)) {
|
||||
goto free_fp_regs;
|
||||
}
|
||||
arch_clone_thread(org, pc, sp, thread);
|
||||
|
||||
memcpy(thread->uctx, org->uctx, sizeof(*org->uctx));
|
||||
@ -432,24 +437,20 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
||||
else {
|
||||
proc = kmalloc(sizeof(struct process), IHK_MC_AP_NOWAIT);
|
||||
if(!proc)
|
||||
goto err_free_proc;
|
||||
goto free_fp_regs;
|
||||
memset(proc, '\0', sizeof(struct process));
|
||||
init_process(proc, org->proc);
|
||||
#ifdef PROFILE_ENABLE
|
||||
proc->profile = org->proc->profile;
|
||||
#endif
|
||||
|
||||
proc->termsig = termsig;
|
||||
asp = create_address_space(cpu_local_var(resource_set), 1);
|
||||
if (!asp) {
|
||||
kfree(proc);
|
||||
goto err_free_proc;
|
||||
goto free_fork_process_proc;
|
||||
}
|
||||
proc->vm = kmalloc(sizeof(struct process_vm), IHK_MC_AP_NOWAIT);
|
||||
if (!proc->vm) {
|
||||
release_address_space(asp);
|
||||
kfree(proc);
|
||||
goto err_free_proc;
|
||||
goto free_fork_process_asp;
|
||||
}
|
||||
memset(proc->vm, '\0', sizeof(struct process_vm));
|
||||
|
||||
@ -457,20 +458,14 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
||||
proc->saved_cmdline = kmalloc(proc->saved_cmdline_len,
|
||||
IHK_MC_AP_NOWAIT);
|
||||
if (!proc->saved_cmdline) {
|
||||
release_address_space(asp);
|
||||
kfree(proc->vm);
|
||||
kfree(proc);
|
||||
goto err_free_proc;
|
||||
goto free_fork_process_vm;
|
||||
}
|
||||
memcpy(proc->saved_cmdline, org->proc->saved_cmdline,
|
||||
proc->saved_cmdline_len);
|
||||
|
||||
dkprintf("fork(): init_process_vm()\n");
|
||||
if (init_process_vm(proc, asp, proc->vm) != 0) {
|
||||
release_address_space(asp);
|
||||
kfree(proc->vm);
|
||||
kfree(proc);
|
||||
goto err_free_proc;
|
||||
goto free_fork_process_cmdline;
|
||||
}
|
||||
memcpy(&proc->vm->numa_mask, &org->vm->numa_mask,
|
||||
sizeof(proc->vm->numa_mask));
|
||||
@ -488,11 +483,8 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
||||
* TODO: do this with COW later? */
|
||||
v->on_fork_vm = proc->vm;
|
||||
if (copy_user_ranges(proc->vm, org->vm) != 0) {
|
||||
release_address_space(asp);
|
||||
v->on_fork_vm = NULL;
|
||||
kfree(proc->vm);
|
||||
kfree(proc);
|
||||
goto err_free_proc;
|
||||
goto free_fork_process_cmdline;
|
||||
}
|
||||
v->on_fork_vm = NULL;
|
||||
|
||||
@ -503,10 +495,9 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
||||
for (cur = org->proc->mckfd; cur; cur = cur->next) {
|
||||
struct mckfd *mckfd = kmalloc(sizeof(struct mckfd), IHK_MC_AP_NOWAIT);
|
||||
if(!mckfd) {
|
||||
release_address_space(asp);
|
||||
kfree(proc->vm);
|
||||
kfree(proc);
|
||||
goto err_free_proc;
|
||||
ihk_mc_spinlock_unlock(&proc->mckfd_lock,
|
||||
irqstate);
|
||||
goto free_fork_process_mckfd;
|
||||
}
|
||||
memcpy(mckfd, cur, sizeof(struct mckfd));
|
||||
|
||||
@ -546,7 +537,10 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
||||
thread->sigcommon = kmalloc(sizeof(struct sig_common),
|
||||
IHK_MC_AP_NOWAIT);
|
||||
if (!thread->sigcommon) {
|
||||
goto err_free_proc;
|
||||
if (clone_flags & CLONE_VM) {
|
||||
goto free_clone_process;
|
||||
}
|
||||
goto free_fork_process_mckfd;
|
||||
}
|
||||
memset(thread->sigcommon, '\0', sizeof(struct sig_common));
|
||||
|
||||
@ -572,8 +566,52 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
||||
|
||||
return thread;
|
||||
|
||||
err_free_proc:
|
||||
ihk_mc_free_pages(thread, KERNEL_STACK_NR_PAGES);
|
||||
/*
|
||||
* free process(clone)
|
||||
* case of (clone_flags & CLONE_VM)
|
||||
*/
|
||||
free_clone_process:
|
||||
goto free_fp_regs;
|
||||
|
||||
/*
|
||||
* free process(fork)
|
||||
* case of !(clone_flags & CLONE_VM)
|
||||
*/
|
||||
free_fork_process_mckfd:
|
||||
{
|
||||
long irqstate = ihk_mc_spinlock_lock(&proc->mckfd_lock);
|
||||
struct mckfd *cur = proc->mckfd;
|
||||
|
||||
while (cur) {
|
||||
struct mckfd *next = cur->next;
|
||||
|
||||
kfree(cur);
|
||||
cur = next;
|
||||
}
|
||||
ihk_mc_spinlock_unlock(&proc->mckfd_lock, irqstate);
|
||||
}
|
||||
free_all_process_memory_range(proc->vm);
|
||||
free_fork_process_cmdline:
|
||||
kfree(proc->saved_cmdline);
|
||||
free_fork_process_vm:
|
||||
kfree(proc->vm);
|
||||
free_fork_process_asp:
|
||||
ihk_mc_pt_destroy(asp->page_table);
|
||||
kfree(asp);
|
||||
free_fork_process_proc:
|
||||
kfree(proc);
|
||||
|
||||
/*
|
||||
* free fp_regs
|
||||
*/
|
||||
free_fp_regs:
|
||||
release_fp_regs(thread);
|
||||
|
||||
/*
|
||||
* free thread
|
||||
*/
|
||||
free_thread:
|
||||
free_thread_pages(thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* syscall.c COPYRIGHT FUJITSU LIMITED 2015-2018 */
|
||||
/* syscall.c COPYRIGHT FUJITSU LIMITED 2015-2019 */
|
||||
/**
|
||||
* \file syscall.c
|
||||
* License details are found in the file LICENSE.
|
||||
@ -120,7 +120,6 @@ extern int num_processors;
|
||||
extern unsigned long ihk_mc_get_ns_per_tsc(void);
|
||||
extern int ptrace_detach(int pid, int data);
|
||||
extern void debug_log(unsigned long);
|
||||
extern void free_all_process_memory_range(struct process_vm *vm);
|
||||
extern int arch_clear_host_user_space();
|
||||
extern long arch_ptrace(long request, int pid, long addr, long data);
|
||||
extern struct cpu_local_var *clv;
|
||||
|
||||
Reference in New Issue
Block a user