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

Reply via email to