diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2008-02-27 08:04:29 -0500 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2008-02-27 08:23:53 -0500 |
commit | 325d6f5593b40b5a48cf4ade74c01681f2ff6044 (patch) | |
tree | facb22a7deb7b6c9ce2bdaf07bcc4ac3bd8d21b5 /arch/avr32 | |
parent | d45ad06273f797f6239b97fd9962ecd81eec847f (diff) |
avr32: Fix OCD refcounting bug
Iff the parent has TIF_DEBUG set, _and_ clone_flags includes
CLONE_PTRACE we should set the TIF_DEBUG flag for the child and
increment the ocd refcount. Otherwise, the TIF_DEBUG flag must be
unset.
Currently, the child inherits TIF_DEBUG from the parent before
copy_thread is called, so TIF_DEBUG may be already be set before we
determine whether the child is supposed to inherit debugging
capabilities from the parent or not. This means that ocd_enable()
won't increment the refcount, because TIF_DEBUG is already set, and
that TIF_DEBUG will be set for processes that aren't being debugged.
This leads to a refcounting asymmetry, which may show up as
------------[ cut here ]------------
Badness at arch/avr32/kernel/ocd.c:73
PC is at ocd_disable+0x34/0x60
LR is at put_lock_stats+0xa/0x20
as reported by David Brownell. Happens when strace'ing a process that
forks a new child process, e.g. "strace mount -tjffs2 mtd1 /mnt", and
subsequently killing the child process (e.g. "umount /mnt".)
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32')
-rw-r--r-- | arch/avr32/kernel/process.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index faf8d0e76801..7f4af0b1e111 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c | |||
@@ -348,6 +348,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | |||
348 | p->thread.cpu_context.ksp = (unsigned long)childregs; | 348 | p->thread.cpu_context.ksp = (unsigned long)childregs; |
349 | p->thread.cpu_context.pc = (unsigned long)ret_from_fork; | 349 | p->thread.cpu_context.pc = (unsigned long)ret_from_fork; |
350 | 350 | ||
351 | clear_tsk_thread_flag(p, TIF_DEBUG); | ||
351 | if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG)) | 352 | if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG)) |
352 | ocd_enable(p); | 353 | ocd_enable(p); |
353 | 354 | ||