int3 ignored during attach

From: Victor Zandy (zandy@cs.wisc.edu)
Date: Wed Apr 26 2000 - 13:26:06 EST


    On x86 Linux 2.2 (2.2.12 and 2.2.14 tested), if a process executes
an int3 instruction while another process attaches to it, the SIGTRAP
can be lost.

    Below is a pair of program that demonstrate this behavior. The
first program (trap) repeatedly executes and handles an int3. The
second program (trace) repeatedly attaches and detaches to its input
pid. When trap is left to itself, it runs forever. When trace is
applied to a trap process, eventually the int3 falls through (to the
fprintf).

    My guess is that attaching to a process between the time it has
entered the kernel for an int3, but before the kernel has set up the
signal handler call, can cause the trap to be lost.

    I would like a way to detect that this is going to happen after I
attach to the process. I have had trace look at the user and debug
registers (everything accessible from ptrace) and the pending signal
state of the inferior, but there is no difference in the state in
cases when the trap is lost and when the trap is handled. Is there
any other state I can inspect that might help me distinguish these
cases?

    Also, can anyone explain why this happens?

Thanks,
Vic Zandy

/* trap.c */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void handler(int sig, struct sigcontext uap)
{
     uap.eip--;
}

int main(int argc, char *argv[])
{
     struct sigaction sa;
     sa.sa_handler = handler;
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = 0;
     sigaction(SIGTRAP, &sa, NULL);
     fprintf(stderr, "pid = %d\n", getpid());
     asm("int3");
     fprintf(stderr, "Done\n");
}

/* trace.c */
#include <stdio.h>
#include <sys/ptrace.h>
#include <stdlib.h>
#include <signal.h>

long int dptrace(enum __ptrace_request req, pid_t pid,
                 void *addr, void *data)
{
     int rv;

     rv = ptrace(req, pid, addr, data);
     if (0 > rv) {
          perror("ptrace");
          exit(1);
     }
     return rv;
}

int main(int argc, char *argv[])
{
     int pid;

     if (argc != 2) {
          fprintf(stderr, "Usage: %s PID\n", argv[0]);
          exit(1);
     }
     pid = atoi(argv[1]);

     while (1) {
          dptrace(PTRACE_ATTACH, pid, 0, 0);
          waitpid(pid, 0, 0);
          dptrace(PTRACE_DETACH, pid, 0, 0);
     }
}

-
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:11 EST