Hi,
I also reproduced likely same error as David in simple PTRACE test.
The checking code in utrace_resume
/*
* If UTRACE_INTERRUPT was just used, we don't bother with a
* report here. We will report and stop in utrace_get_signal().
*/
if (unlikely(utrace->interrupt)) {
BUG_ON(!signal_pending(task));
return;
}
is triggered.
The attachment are testcase and error message. The testcase works fine
on vanilla 2.6.26 kernel.
Regards,
Wenji
------------[ cut here ]------------
kernel BUG at kernel/utrace.c:1638!
invalid opcode: 0000 [#4] SMP
Modules linked in:
Pid: 4514, comm: ptrace-syscall- Tainted: G D W (2.6.26 #1)
EIP: 0060:[<c013da9c>] EFLAGS: 00010046 CPU: 0
EIP is at utrace_resume+0x56/0xc2
EAX: cb8c6000 EBX: cf213260 ECX: 00000000 EDX: cb8c7fb8
ESI: cf2eaa50 EDI: cb8c7f98 EBP: cb8c6000 ESP: cb8c7f8c
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process ptrace-syscall- (pid: 4514, ti=cb8c6000 task=cf2eaa50 task.ti=cb8c6000)
Stack: 00000005 00000000 00000000 bfa7e5b4 00000100 cb8c7fb8 bfa7e540 c01032eb
08048ace bfa7e5b4 c01034c6 08048ace 00000004 00458ff4 bfa7e5b4 bfa7e540
bfa7e528 00000000 0000007b 0000007b 00000000 00000021 b7f80424 00000073
Call Trace:
[<c01032eb>] do_notify_resume+0x38/0x55
[<c01034c6>] work_notifysig+0x13/0x19
=======================
Code: 43 ba 25 00 0f b6 43 18 24 f7 a8 02 88 43 18 0f 94 c0 0f b6 c0 fe 43 10
85 c0 75 74 f6 43 18 04 74 0d 8b 46 04 f6 40 08 02 75 65 <0f> 0b eb fe 89 d8 e8
c0 f7 ff ff 8b 4b 08 8d 43 08 8b 39 39 c1
EIP: [<c013da9c>] utrace_resume+0x56/0xc2 SS:ESP 0068:cb8c7f8c
---[ end trace 4eaa2a86a8e2da22 ]---
#include <signal.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <unistd.h>
#include <sched.h>
#include <assert.h>
#include <asm/unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <errno.h>
#if defined __x86_64__ || defined __i386__
#define LOOP 10
static pid_t child;
static void
cleanup (void)
{
if (child != 0)
kill (child, SIGKILL);
}
static void
handler_fail (int signo)
{
cleanup ();
signal (SIGABRT, SIG_DFL);
assert (0);
}
int main(int argc, char **argv) {
int status, j;
long l;
pid_t pid;
setbuf (stdout, NULL);
atexit (cleanup);
signal (SIGABRT, handler_fail);
child = fork();
switch (child)
{
case -1:
assert(0);
case 0:
{ l = ptrace(PTRACE_TRACEME, 0, 0, 0);
assert(l==0);
raise(SIGSTOP);
while (1) {
l = access(".",R_OK);
assert(l==0);
}
assert(0); //not reached
} //end child
default:
break;
}
pid = waitpid(child, &status, 0);
assert(pid==child);
assert(WIFSTOPPED(status));
assert(WSTOPSIG(status) == SIGSTOP);
l = ptrace(PTRACE_SYSCALL,child, 0, 0);
assert(l==0);
j = 0;
while (j < LOOP){
pid = waitpid(child, &status, 0);
assert(child==pid);
assert(WIFSTOPPED(status));
assert(WSTOPSIG(status) == SIGTRAP);
l = ptrace(PTRACE_SYSCALL, child, 0, 0);
assert(l==0);
j++;
} //end loop
pid = waitpid(child, &status, 0);
assert(pid==child);
assert(WIFSTOPPED(status));
assert(WSTOPSIG(status) == SIGTRAP);
l = ptrace(PTRACE_CONT, child, 0, SIGKILL);
if (l < 0) {
error (0, errno,"PTRACE_CONT, pid %ld, retvalue %ld",(long)child,l);
return 1;
}
else
assert(l==0);
pid = waitpid(child, &status, 0);
assert(child==pid);
if (WIFEXITED(status) && WTERMSIG(status)!=SIGKILL)
return 1;
return 0;
} //end main
#else
int main(int argc, char **argv) {
return 77;
}
#endif