diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 37 | 
1 files changed, 29 insertions, 8 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 52e725d4a866..beb31725f7e2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -799,6 +799,29 @@ struct file *get_mm_exe_file(struct mm_struct *mm)  EXPORT_SYMBOL(get_mm_exe_file);  /** + * get_task_exe_file - acquire a reference to the task's executable file + * + * Returns %NULL if task's mm (if any) has no associated executable file or + * this is a kernel thread with borrowed mm (see the comment above get_task_mm). + * User must release file via fput(). + */ +struct file *get_task_exe_file(struct task_struct *task) +{ +	struct file *exe_file = NULL; +	struct mm_struct *mm; + +	task_lock(task); +	mm = task->mm; +	if (mm) { +		if (!(task->flags & PF_KTHREAD)) +			exe_file = get_mm_exe_file(mm); +	} +	task_unlock(task); +	return exe_file; +} +EXPORT_SYMBOL(get_task_exe_file); + +/**   * get_task_mm - acquire a reference to the task's mm   *   * Returns %NULL if the task has no mm.  Checks PF_KTHREAD (meaning @@ -913,14 +936,12 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)  	deactivate_mm(tsk, mm);  	/* -	 * If we're exiting normally, clear a user-space tid field if -	 * requested.  We leave this alone when dying by signal, to leave -	 * the value intact in a core dump, and to save the unnecessary -	 * trouble, say, a killed vfork parent shouldn't touch this mm. -	 * Userland only wants this done for a sys_exit. +	 * Signal userspace if we're not exiting with a core dump +	 * because we want to leave the value intact for debugging +	 * purposes.  	 */  	if (tsk->clear_child_tid) { -		if (!(tsk->flags & PF_SIGNALED) && +		if (!(tsk->signal->flags & SIGNAL_GROUP_COREDUMP) &&  		    atomic_read(&mm->mm_users) > 1) {  			/*  			 * We don't check the error code - if userspace has @@ -1404,7 +1425,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,  	p->real_start_time = ktime_get_boot_ns();  	p->io_context = NULL;  	p->audit_context = NULL; -	threadgroup_change_begin(current);  	cgroup_fork(p);  #ifdef CONFIG_NUMA  	p->mempolicy = mpol_dup(p->mempolicy); @@ -1556,6 +1576,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,  	INIT_LIST_HEAD(&p->thread_group);  	p->task_works = NULL; +	threadgroup_change_begin(current);  	/*  	 * Ensure that the cgroup subsystem policies allow the new process to be  	 * forked. It should be noted the the new process's css_set can be changed @@ -1656,6 +1677,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,  bad_fork_cancel_cgroup:  	cgroup_cancel_fork(p);  bad_fork_free_pid: +	threadgroup_change_end(current);  	if (pid != &init_struct_pid)  		free_pid(pid);  bad_fork_cleanup_thread: @@ -1688,7 +1710,6 @@ bad_fork_cleanup_policy:  	mpol_put(p->mempolicy);  bad_fork_cleanup_threadgroup_lock:  #endif -	threadgroup_change_end(current);  	delayacct_tsk_free(p);  bad_fork_cleanup_count:  	atomic_dec(&p->cred->user->processes);  |