PTRACE_SETOPTIONS tests

Submitted by Anonymous
on September 10, 2005 - 12:51pm

Hi, I was doing little tests with the PTRACE_SETOPTIONS of ptrace syscall and I get rare results. Here is the program I made to test:
--------------------- test.c ------------------------------------

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sched.h>
#define PTRACE_EVENT_FORK 1
#define PTRACE_EVENT_VFORK 2
#define PTRACE_EVENT_CLONE 3
#define PTRACE_EVENT_EXEC 4
#define PTRACE_EVENT_VFORK_DONE 5
#define PTRACE_EVENT_EXIT 6
#define PTRACE_SETOPTIONS 0x4200
#define PTRACE_GETEVENTMSG 0x4201
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_O_TRACEFORK 0x00000002
#define PTRACE_O_TRACEVFORK 0x00000004
#define PTRACE_O_TRACECLONE 0x00000008
#define PTRACE_O_TRACEEXEC 0x00000010
#define PTRACE_O_TRACEVFORKDONE 0x00000020
#define PTRACE_O_TRACEEXIT 0x00000040
#define PALL PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACEEXIT
int clone_test(void *arg) { _exit(0) ; }
int main()
{
pid_t pid, npid ;
int status, event ;
char *stack ;
pid = fork();
if(pid == 0)
{
ptrace(PTRACE_TRACEME,0,NULL,NULL) ;
sleep(1) ;
puts("\n ----- Starting test ----- ") ;
puts(" Testing fork...") ;
if (fork() == 0) { exit(0) ; }
puts(" Testing vfork...") ;
if (vfork() == 0) { _exit(0) ; }
puts(" Testing clone...") ;
stack = malloc(4096) ;
clone(clone_test,&stack[4095],CLONE_PARENT | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD,NULL) ;
sleep(1) ;
free(stack) ;
puts(" Testing execve...") ;
execve("./test2",NULL,NULL) ;
puts(" wtf? o_O") ;
exit(-1) ;
}
sleep(1) ;
ptrace(PTRACE_SETOPTIONS,pid,NULL,PALL) ;
Loop:
wait4(-1,&status,0,0) ;
if (WIFSTOPPED(status))
{
if (WSTOPSIG(status) == SIGTRAP)
{
event = (status >> 16) & 0xffff ;
ptrace(PTRACE_GETEVENTMSG,pid,NULL,&npid) ;
switch(event)
{
case PTRACE_EVENT_FORK:
printf(" [%d] fork event!\n",npid) ;
break ;
case PTRACE_EVENT_VFORK:
printf(" [%d] vfork event!\n",npid) ;
break ;
case PTRACE_EVENT_CLONE:
printf(" [%d] clone event!\n",npid) ;
ptrace(PTRACE_CONT,pid,NULL,WSTOPSIG(status)) ;
ptrace(PTRACE_CONT,npid,NULL,WSTOPSIG(status)) ;
break ;
case PTRACE_EVENT_EXEC:
printf(" [%d] execve event!\n",npid) ;
break ;
case PTRACE_EVENT_VFORK_DONE:
printf(" [%d] vfork done event!\n",npid) ;
ptrace(PTRACE_CONT,pid,NULL,WSTOPSIG(status)) ;
ptrace(PTRACE_CONT,npid,NULL,WSTOPSIG(status)) ;
break ;
case PTRACE_EVENT_EXIT:
printf(" [%d] exit event!\n",npid) ;
default:
printf(" [%d] unknow event :S\n",npid) ;
ptrace(PTRACE_CONT,pid,NULL,WSTOPSIG(status)) ;
ptrace(PTRACE_CONT,npid,NULL,WSTOPSIG(status)) ;
}
}
else
{
printf(" Signal nº: %d | continuing\n",WSTOPSIG(status)) ;
ptrace(PTRACE_CONT,pid,NULL,WSTOPSIG(status)) ;
ptrace(PTRACE_CONT,npid,NULL,WSTOPSIG(status)) ;
}
}
goto Loop ;
return 0 ;
}

------------------------------ test2.c --------------------------------

#include <stdlib.h>
int main()
{
puts(" ----- Test finished -----") ;
exit(0) ;
}

------------------------------------------------------------------------

I compiled:

gcc test.c -o test
gcc test2.c -o test2

And when i run:

# ./test

----- Starting test -----
Testing fork...
Signal nº: 17 | continuing
Testing vfork...
[6790] vfork event!
Signal nº: 19 | continuing
Signal nº: 19 | continuing
[6790] exit event!
[6790] unknow event :S
[6790] vfork done event!
Testing clone...
[6791] clone event!
Signal nº: 17 | continuing
Testing execve...

And it hangs on execve. I don't know why in fork is not working, and what is the unknow event. And why it stops on execve???

But more strange things, when I run other times, sometimes I get diferent results, like this:

# ./test

----- Starting test -----
Testing fork...
Signal nº: 17 | continuing
Testing vfork...
[6910] vfork event!
Signal nº: 19 | continuing
Signal nº: 19 | continuing
[6910] exit event!
[6910] unknow event :S
[6910] vfork done event!
Testing clone...
[6911] clone event!
Signal nº: 17 | continuing
[0] exit event!
[0] unknow event :S

And stops there.
But other times, and ALWAYS I run it on a real tyy I get this:

# ./test

----- Starting test -----
Testing fork...
Signal nº: 17 | continuing
Testing vfork...
Signal nº: 17 | continuing
Testing clone...

Some ideas? I really don't know what is happening.
Thanks (sorry for my english)