Bug in JIAJIA

JIAJIA can not catch the fault address correctly in sigsevg_handler for x86_64

http://us.generation-nt.com/answer/sigsegv-signal-handler-help-183484481.html

http://comp.os.linux.development.apps.narkive.com/wH6d4yNJ/fail-to-get-the-fault-address-from-sigcontext-cr2

http://sourceware.org/ml/libc-help/2009-10/msg00021.html
http://comp.os.linux.development.apps.narkive.com/wH6d4yNJ/fail-to-get-the-fault-address-from-sigcontext-cr2

In JIAJIA/src/mem.c line 462


In 32-bit system, sigctx_cr2 record the fault address 200000, but not in 64-bit.

sigsegv.c

#include <time.h>
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <string.h>

void my_sigsegv(int signo, struct sigcontext sigctx)
{
    printf("Produce sigsegv %d\n",signo);
    printf("%ld:\n",sigctx.cr2);
    return ;
}

int main()
{
    struct sigaction act;
    act.sa_handler =  my_sigsegv ;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGSEGV , &act , NULL);

    char *pstr = 200000;
    strcpy(pstr , "hello");
}


Solution (man sigaction for details)

In mem.c line 170
#ifdef LINUX
    jiamapfd=open("/dev/zero", O_RDWR,0);
    { 
        /*struct sigaction act;
          act.sa_handler = (void_func_handler)sigsegv_handler;
          sigemptyset(&act.sa_mask);
          act.sa_flags = SA_NOMASK;
          if (sigaction(SIGSEGV, &act, NULL))
          assert0(0,"segv sigaction problem");*/


        //xiao
        struct sigaction act;
        // act.sa_handler = (void_func_handler)sigsegv_handler;
        act.sa_sigaction = sigsegv_handler;
        sigemptyset(&act.sa_mask);
        // act.sa_flags = SA_NOMASK;
        act.sa_flags = SA_NOMASK | SA_SIGINFO;
        if (sigaction(SIGSEGV, &act, NULL))
            assert0(0,"segv sigaction problem");


    }

In mem.c line 481

#ifdef LINUX
    //void sigsegv_handler(int signo, struct sigcontext sigctx)
    //xiao_bug
    //void sigsegv_handler( int sig, siginfo_t *sip,struct sigcontext *scp)
    //xiao_bug:
void sigsegv_handler (int signo, struct siginfo *info, void *data)
    //http://comp.os.linux.development.apps.narkive.com/wH6d4yNJ/fail-to-get-the-fault-address-from-sigcontext-cr2
#endif 

In mem.c line 75

#ifdef LINUX 
//void sigsegv_handler(int, struct sigcontext);
//xiao
//void sigsegv_handler( int sig, siginfo_t *sip,struct sigcontext *scp);
//xiao
void sigsegv_handler (int signo, struct siginfo *info, void *data);
#endif

In mem.c line 526

#ifdef LINUX
    /*faultaddr = (address_t) sigctx.cr2;
      faultaddr = (address_t) ((unsigned long) faultaddr/Pagesize*Pagesize);
      writefault = (int) sigctx.err & 2;*/


    //xiao
    DPRINTF("Come to linux\n");
    DPRINTF("errno:%d code:%d addr:0x%x\n",info->si_errno,info->si_code,info->si_addr);
    faultaddr = (address_t)info->si_addr;
    DPRINTF("faultaddr=%lx\n",(long)faultaddr);
    faultaddr = (address_t) ((unsigned long) faultaddr/Pagesize*Pagesize);
    //how to get the writfualt
    //writefault = (int) info->si_errno & 2;


#endif 


access type (READ or WRITE) during SEGV 

http://computer-programming-forum.com/46-asm/81c68464056ab13a.htm

In /usr/include/x86_64-linux-gnu/sys/ucontext.h  40 line (For user space to use the register)

//xiao
#ifndef __USE_GNU
#define __USE_GNU
#endif

#include <time.h>   
 #include <stdio.h>   
 #include <sys/time.h>   
 #include <signal.h>   
 #include <string.h>   
 #include <sys/ucontext.h> 
  
 void my_sigsegv(int signo, struct siginfo * info, void * data)   
 {   
     printf("Produce sigsegv %d\n",signo);   
     printf("%ld\n",(long)info->si_addr); 
     struct ucontext *ucp = (struct ucontext *)data; 
     printf("REG_ERR:%d\n",ucp->uc_mcontext.gregs[REG_ERR]); 
     int type = ucp->uc_mcontext.gregs[REG_ERR] & 2; 
     printf("type=%d\n",type); 
     if(type == 2) { 
         printf("write\n"); 
     }else { 
         printf("read\n"); 
     } 
     return ;   
 }   
  
 int main()   
 {   
     struct sigaction act;   
     act.sa_sigaction =  my_sigsegv;   
     sigemptyset(&act.sa_mask);   
     act.sa_flags = SA_SIGINFO;   
     sigaction(SIGSEGV, &act, NULL);   
  
     char *pstr = 200000;   
    // *pstr = 31; 
  //   *pstr = 0; 
     printf("%c\n", *pstr); 
 //    strcpy(pstr,"hello");   
 }   


#include <time.h>     
 #include <stdio.h>     
 #include <sys/time.h>     
 #include <signal.h>     
 #include <string.h>     
 #include <sys/ucontext.h> 
 #include <sys/mman.h>
 #include <fcntl.h>
 long jiamapfd = 0;
 void my_sigsegv(int signo, struct siginfo * info, void * data)     
 {     
     printf("Produce sigsegv %d\n",signo);     
     printf("faultaddr:%lx\n",(long)info->si_addr);   
     long faultaddr = (long)info->si_addr;
     struct ucontext *ucp = (struct ucontext *)data;   
    // printf("REG_ERR:%d\n",ucp->uc_mcontext.gregs[REG_ERR]);   
     int type = ucp->uc_mcontext.gregs[REG_ERR] & 2;   
     type = (type==0)?0:1;
     if(type == 1) {   
         printf("write fault\n");   
     }else {   
         printf("read fault\n");   
     }   
     long  mapad= (long)mmap(faultaddr,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,jiamapfd,0);
     printf("Map:0x%lx\n",mapad);
     return ;     
 }     
 
 int main()     
 {     
     struct sigaction act;     
     act.sa_sigaction =  my_sigsegv;     
     sigemptyset(&act.sa_mask);     
     act.sa_flags = SA_SIGINFO;     
     sigaction(SIGSEGV, &act, NULL);     
     jiamapfd = open("/dev/zero",O_RDWR,0);
    char * p = 0x70000000;
    *p = *p + 3;
    printf("%c\n",*p);
    char *s = 0x70003000;
    *s = 5;
 }

Produce sigsegv 11
faultaddr:70000000
read fault
Map:0x70000000

Produce sigsegv 11
faultaddr:70003000
write fault
Map:0x70003000


發佈了52 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章