[PATCH] ptrace bugfix, part 2

From: Manfred Spraul (manfreds@colorfullife.com)
Date: Sun Apr 30 2000 - 11:39:05 EST


With task_lock() and get_task_struct, it's now possible to synchronize
ptrace() and exit() properly.

I've attached a preliminary patch, but what should I do when someone
tries to ptrace a ZOMBIE? Is that possible?

I tested the patch with gdb & strace, everything seems to be fine.

--
	Manfred

// $Header$ // Kernel Version: // VERSION = 2 // PATCHLEVEL = 3 // SUBLEVEL = 99 // EXTRAVERSION = -pre6 --- 2.3/kernel/ptrace.c Thu Apr 27 11:27:26 2000 +++ build-2.3/kernel/ptrace.c Sun Apr 30 17:32:02 2000 @@ -123,6 +123,10 @@ /* Worry about races with exit() */ lock_kernel(); mm = tsk->mm; + if(!mm) { + unlock_kernel(); + return 0; + } atomic_inc(&mm->mm_users); unlock_kernel(); --- 2.3/arch/i386/kernel/ptrace.c Fri Jan 21 13:08:25 2000 +++ build-2.3/arch/i386/kernel/ptrace.c Sun Apr 30 18:28:33 2000 @@ -151,15 +151,20 @@ ret = -ESRCH; read_lock(&tasklist_lock); child = find_task_by_pid(pid); - read_unlock(&tasklist_lock); /* FIXME!!! */ + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); if (!child) goto out; + task_lock(child); ret = -EPERM; if (pid == 1) /* you may not mess with init */ - goto out; + goto out_tsk; + /* FIXME: ptracing a ZOMBIE? */ + if (request == PTRACE_ATTACH) { if (child == current) - goto out; + goto out_tsk; if ((!child->dumpable || (current->uid != child->euid) || (current->uid != child->suid) || @@ -168,10 +173,10 @@ (current->gid != child->sgid) || (!cap_issubset(child->cap_permitted, current->cap_permitted)) || (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out; + goto out_tsk; /* the same process cannot be attached many times */ if (child->flags & PF_PTRACED) - goto out; + goto out_tsk; child->flags |= PF_PTRACED; write_lock_irqsave(&tasklist_lock, flags); @@ -184,17 +189,17 @@ send_sig(SIGSTOP, child, 1); ret = 0; - goto out; + goto out_tsk; } ret = -ESRCH; if (!(child->flags & PF_PTRACED)) - goto out; + goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) - goto out; + goto out_tsk; } if (child->p_pptr != current) - goto out; + goto out_tsk; switch (request) { /* when I and D space are separate, these will need to be fixed. */ @@ -270,7 +275,7 @@ data &= ~DR_CONTROL_RESERVED; for(i=0; i<4; i++) if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) - goto out; + goto out_tsk; } addr -= (long) &dummy->u_debugreg; @@ -435,6 +440,9 @@ ret = -EIO; break; } +out_tsk: + task_unlock(child); + free_task_struct(child); out: unlock_kernel(); return ret;

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Apr 30 2000 - 21:00:18 EST