Пример #1
0
void syscall_trace_leave(struct pt_regs *regs)
{
    if (isaudit(current) && (current->ptrace & PT_AUDITED))
        audit_result(regs);

    if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) == (PT_PTRACED|PT_TRACESYS))
        syscall_ptrace();
}
Пример #2
0
/*
 *  Ok, this is the main fork-routine.
 *
 * It copies the process, and if successful kick-starts
 * it and waits for it to finish using the VM if required.
 */
int do_fork(unsigned long clone_flags,
	    unsigned long stack_start,
	    struct pt_regs *regs,
	    unsigned long stack_size,
	    int *parent_tidptr,
	    int *child_tidptr)
{
	struct task_struct *p;
	int trace = 0;
	pid_t pid;

	if (unlikely(current->ptrace)) {
		trace = fork_traceflag (clone_flags);
		if (trace)
			clone_flags |= CLONE_PTRACE;
	}

	p = copy_process(clone_flags, stack_start, regs, stack_size, 
			 parent_tidptr, child_tidptr);

	if (unlikely(IS_ERR(p))) 
		return (int) PTR_ERR(p);
	else {
		struct completion vfork;

         	/*
	         * Do this prior waking up the new thread - the thread pointer
       	  	 * might get invalid after that point, if the thread exits 
		 * quickly.
       		 */
		pid = p->pid;
		if (clone_flags & CLONE_VFORK) {
			p->vfork_done = &vfork;
			init_completion(&vfork);
		}

		if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) {
			/*
			 * We'll start up with an immediate SIGSTOP.
			 */
			sigaddset(&p->pending.signal, SIGSTOP);
			p->sigpending = 1;
		}

		if (isaudit(current))
			audit_fork(current, p);

		/*
		 * The task is in TASK_UNINTERRUPTIBLE right now, no-one
		 * can wake it up. Either wake it up as a child, which
		 * makes it TASK_RUNNING - or make it TASK_STOPPED, after
		 * which signals can wake the child up.
		 */
		if (!(clone_flags & CLONE_STOPPED))
			wake_up_forked_process(p);	/* do this last */
		else
			p->state = TASK_STOPPED;
		++total_forks;

		if (unlikely (trace)) {
			current->ptrace_message = (unsigned long) pid;
			ptrace_notify((trace << 8) | SIGTRAP);
		}

		if (clone_flags & CLONE_VFORK) {
			wait_for_completion(&vfork);
			if (unlikely(current->ptrace & PT_TRACE_VFORK_DONE))
				ptrace_notify((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
		} else
			/*
			 * Let the child process run first, to avoid most of the
			 * COW overhead when the child exec()s afterwards.
			 */
			set_need_resched();
	}
	return pid;
}