In the MIPS entry.S the symbol resume_userspace to the call to
do_notify_resume form a loop through which the kernel will iterate as
long as work is pending. If we iterate through this loop more than once
with no signal pending for at least one but the last iteration we will
perform the syscall restarting multiple times resulting in a syscall
return prior to the the syscall instruction in userspace because the
return program counter will be adjusted several times by:
regs->regs[7] = regs->regs[26];
regs->cp0_epc -= 8;
resulting in return to userspace at a too low address. On MIPS this often
happens to be a stackpointer adjustment but in many cases this may also
just be a harmless instruction such as reloading the syscall number so
may go unnoticed.
We were able to trigger this when debugging a multithreaded programs.
At least i386 uses virtually identical algorithms so I think is likely
to have the same issue.
The fix in case of MIPS is trivial:
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 73f8aad..8676055 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -465,6 +464,7 @@ void do_signal(struct pt_regs *regs)
regs->regs[7] = regs->regs[26];
regs->cp0_epc -= 4;
}
+ regs->regs[0] = 0; /* Don't deal with this again. */
}
/*
Ralf
-
To unsubscribe from this list: send the line "unsubscribe linux-arch" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html