int ptrace_attach(struct task_struct *task) { int retval; task_lock(task); retval = -EPERM; if (task->pid <= 1) goto bad; if (task->tgid == current->tgid) goto bad; /* the same process cannot be attached many times */ if (task->ptrace & PT_PTRACED) goto bad; retval = may_attach(task); if (retval) goto bad; /* Go */ task->ptrace |= PT_PTRACED | ((task->real_parent != current) ? PT_ATTACHED : 0); if (capable(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; task_unlock(task); write_lock_irq(&tasklist_lock); __ptrace_link(task, current); write_unlock_irq(&tasklist_lock); force_sig_specific(SIGSTOP, task); return 0; bad: task_unlock(task); return retval; }
int ptrace_attach(struct task_struct *task) { int retval; audit_ptrace(task); retval = -EPERM; if (task->pid <= 1) goto out; if (task->tgid == current->tgid) goto out; repeat: /* * Nasty, nasty. * * We want to hold both the task-lock and the * tasklist_lock for writing at the same time. * But that's against the rules (tasklist_lock * is taken for reading by interrupts on other * cpu's that may have task_lock). */ task_lock(task); local_irq_disable(); if (!write_trylock(&tasklist_lock)) { local_irq_enable(); task_unlock(task); do { cpu_relax(); } while (!write_can_lock(&tasklist_lock)); goto repeat; } if (!task->mm) goto bad; /* the same process cannot be attached many times */ if (task->ptrace & PT_PTRACED) goto bad; retval = may_attach(task); if (retval) goto bad; /* Go */ task->ptrace |= PT_PTRACED | ((task->real_parent != current) ? PT_ATTACHED : 0); if (capable(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; __ptrace_link(task, current); force_sig_specific(SIGSTOP, task); bad: write_unlock_irq(&tasklist_lock); task_unlock(task); out: return retval; }
static inline void freeze_process(struct task_struct *p) { unsigned long flags; if (!freezing(p)) { rmb(); if (!frozen(p)) { if (p->state == TASK_STOPPED) force_sig_specific(SIGSTOP, p); freeze(p); spin_lock_irqsave(&p->sighand->siglock, flags); signal_wake_up(p, p->state == TASK_STOPPED); spin_unlock_irqrestore(&p->sighand->siglock, flags); } } }
int ptrace_attach(struct task_struct *task) { int retval; task_lock(task); retval = -EPERM; if (task->pid <= 1) goto bad; if (task == current) goto bad; if (!task->mm) goto bad; if(((current->uid != task->euid) || (current->uid != task->suid) || (current->uid != task->uid) || (current->gid != task->egid) || (current->gid != task->sgid) || (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) goto bad; rmb(); if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) goto bad; /* the same process cannot be attached many times */ if (task->ptrace & PT_PTRACED) goto bad; retval = security_ptrace(current, task); if (retval) goto bad; /* Go */ task->ptrace |= PT_PTRACED; if (capable(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; task_unlock(task); write_lock_irq(&tasklist_lock); __ptrace_link(task, current); write_unlock_irq(&tasklist_lock); force_sig_specific(SIGSTOP, task); return 0; bad: task_unlock(task); return retval; }
static void send_fake_signal(struct task_struct *p) { if (p->state == TASK_STOPPED) force_sig_specific(SIGSTOP, p); fake_signal_wake_up(p, p->state == TASK_STOPPED); }