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(); }
/* * 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; }