static int ptrace_detach(struct task_struct *child, unsigned int data) { bool dead = false; if (!valid_signal(data)) return -EIO; /* Architecture-specific hardware disable .. */ ptrace_disable(child); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); write_lock_irq(&tasklist_lock); /* * This child can be already killed. Make sure de_thread() or * our sub-thread doing do_wait() didn't do release_task() yet. */ if (child->ptrace) { child->exit_code = data; dead = __ptrace_detach(current, child); } write_unlock_irq(&tasklist_lock); if (unlikely(dead)) release_task(child); return 0; }
SYSCALL_DEFINE2( smunch, int, pid, unsigned long, bit_pattern) { struct task_struct *target; unsigned long flags; rcu_read_lock(); target=find_task_by_vpid(pid); rcu_read_unlock(); if(!target) { printk(KERN_ALERT "TARGET DOESNT EXIST\n"); return -1;} if(!lock_task_sighand(target, &flags)) { printk(KERN_ALERT "Could not acquire sighand lock\n"); return -1;} if(!thread_group_empty(target)) { printk(KERN_ALERT "Multi threaded process\n"); unlock_task_sighand(target , &flags); return -1; } if((target->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) && (bit_pattern & (1<<(SIGKILL-1)))) { printk(KERN_ALERT " killing process with PID %d\n",pid); unlock_task_sighand(target, &flags); release_task(target); } else { sigaddsetmask(&(target->signal->shared_pending.signal),bit_pattern); wake_up_process(target); unlock_task_sighand(target, &flags); } return 0; }
SYSCALL_DEFINE2(smunch, pid_t,pid, long, bit_pattern){ //Check if multi threaded struct task_struct *p; bool ret; p = pid_task(find_vpid(pid), PIDTYPE_PID); if(!p){ pr_alert("\nprocess table is null"); return -1; } ret = current_is_single_threaded(); if(ret == false){ pr_alert("\nError : Multithreaded process, cannot proceed\n"); return -1; } //Check if traced if(p->ptrace & PT_PTRACED){ pr_alert("\nError : Traced process, cannot proceed\n"); return -1; } //Check if zombie state if(p->exit_state == EXIT_ZOMBIE){ if((1 << (SIGKILL-1)) & bit_pattern){ release_task(p); } return 0; } else{ p->pending.signal.sig[0] |= bit_pattern; wake_up_process(p); } return 0; }
int ptrace_detach(struct task_struct *child, unsigned int data) { int dead = 0; if (!valid_signal(data)) return -EIO; /* Architecture-specific hardware disable .. */ ptrace_disable(child); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); write_lock_irq(&tasklist_lock); /* protect against de_thread()->release_task() */ if (child->ptrace) { child->exit_code = data; dead = __ptrace_detach(current, child); if (!child->exit_state) wake_up_process(child); } write_unlock_irq(&tasklist_lock); if (unlikely(dead)) release_task(child); return 0; }
SYSCALL_DEFINE2(smunch,int,pid,unsigned long,bit_pattern) { unsigned long flags; struct task_struct *task; rcu_read_lock(); task = pid_task(find_vpid(pid),PIDTYPE_PID); rcu_read_unlock(); if(!task) return -1; // Process not present if(!lock_task_sighand(task,&flags)) { //Process refuses to give the lock. Either dead/dying unlock_task_sighand(task,&flags); return -1; } if(!thread_group_empty(task)) { printk(KERN_ALERT "\nMULTI-Threaded Process, Exiting without processing"); ret=-1; goto return_path; } printk(KERN_ALERT "\nExit State:%XH,State=%XH\n",task->exit_state,task->state); //Info to user if(task->state & TASK_UNINTERRUPTIBLE) printk(KERN_ALERT "\nProcess is in Uniterruptible Wait-DeepSleep!!"); // Info to User if(bit_pattern & (1UL<<(SIGKILL-1)) && (task->exit_state & EXIT_ZOMBIE)) { printk(KERN_ALERT "\nSIGKILL present while Process is Zombie, releasing task!!"); unlock_task_sighand(task,&flags); release_task(task); // detach_pid is called from release_task() return 0; } /* If !SIGKILL || (ordinary process) || DeepSleep, sending all signals. It is Users responsility to note that signals will get handled from 1-64 order*/ printk(KERN_ALERT "!SIGKILL || (ordinary process) || DeepSleep, sending all signals!"); task->signal->shared_pending.signal.sig[0] = bit_pattern; set_tsk_thread_flag(task,TIF_SIGPENDING); signal_wake_up(task,1); ret=0; return_path: unlock_task_sighand(task,&flags); return ret; }
int __KT_try_releasing_tasks() { struct llistnode *cur; rwlock_acquire(&kill_queue->rwl, RWL_WRITER); if(ll_is_empty(kill_queue)) { rwlock_release(&kill_queue->rwl, RWL_WRITER); return 0; } task_t *t=0; ll_for_each_entry(kill_queue, cur, task_t *, t) { /* need to check for orphaned zombie tasks */ if(t->flags & TF_BURIED && (t != ((cpu_t *)t->cpu)->cur)) { if(t->parent == 0 || t->parent->state == TASK_DEAD || (t->parent->flags & TF_KTASK) || t->parent == kernel_task) move_task_to_kill_queue(t, 0); if(t->flags & TF_KILLREADY) break; } } if(!t || !((t->flags & TF_BURIED) && (t->flags & TF_KILLREADY))) { rwlock_release(&kill_queue->rwl, RWL_WRITER); return 0; } assert(cur->entry == t); void *node = ll_do_remove(kill_queue, cur, 1); assert(node == cur); int ret = 0; if(!ll_is_empty(kill_queue)) ret = 1; rwlock_release(&kill_queue->rwl, RWL_WRITER); release_task(t); kfree(cur); return ret; }
asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru) { int flag, retval; DECLARE_WAITQUEUE(wait, current); struct task_struct *tsk; if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL)) return -EINVAL; add_wait_queue(¤t->wait_chldexit,&wait); repeat: flag = 0; current->state = TASK_INTERRUPTIBLE; read_lock(&tasklist_lock); tsk = current; do { struct task_struct *p; for (p = tsk->p_cptr ; p ; p = p->p_osptr) { if (pid>0) { if (p->pid != pid) continue; } else if (!pid) { if (p->pgrp != current->pgrp) continue; } else if (pid != -1) { if (p->pgrp != -pid) continue; } /* Wait for all children (clone and not) if __WALL is set; * otherwise, wait for clone children *only* if __WCLONE is * set; otherwise, wait for non-clone children *only*. (Note: * A "clone" child here is one that reports to its parent * using a signal other than SIGCHLD.) */ if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0)) && !(options & __WALL)) continue; flag = 1; switch (p->state) { case TASK_STOPPED: if (!p->exit_code) continue; if (!(options & WUNTRACED) && !(p->ptrace & PT_PTRACED)) continue; read_unlock(&tasklist_lock); retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; if (!retval && stat_addr) retval = put_user((p->exit_code << 8) | 0x7f, stat_addr); if (!retval) { p->exit_code = 0; retval = p->pid; } goto end_wait4; case TASK_ZOMBIE: current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime; current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime; read_unlock(&tasklist_lock); retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; if (!retval && stat_addr) retval = put_user(p->exit_code, stat_addr); if (retval) goto end_wait4; retval = p->pid; if (p->p_opptr != p->p_pptr) { write_lock_irq(&tasklist_lock); REMOVE_LINKS(p); p->p_pptr = p->p_opptr; SET_LINKS(p); do_notify_parent(p, SIGCHLD); write_unlock_irq(&tasklist_lock); } else release_task(p); goto end_wait4; default: continue; } } if (options & __WNOTHREAD) break; tsk = next_thread(tsk); } while (tsk != current); read_unlock(&tasklist_lock); if (flag) { retval = 0; if (options & WNOHANG) goto end_wait4; retval = -ERESTARTSYS; if (signal_pending(current)) goto end_wait4; schedule(); goto repeat; } retval = -ECHILD; end_wait4: current->state = TASK_RUNNING; remove_wait_queue(¤t->wait_chldexit,&wait); return retval; }
static void exit_notify(struct task_struct *tsk) { //... if (state == TASK_DEAD) release_task(tsk); }