Ignore:
Timestamp:
Jul 2, 2008 4:35:26 PM (6 years ago)
Author:
sam
Message:
  • Fork the grabbed process and exit the parent. Unfortunately for some reason it still survives as a zombie, there must be something wrong with the setsid/setpgid mechanism we use (maybe setpgrp is needed?).
File:
1 edited

Legend:

Unmodified
Added
Removed
  • neercs/trunk/src/mytrace.c

    r2514 r2516  
    3939static int memcpy_into_target(struct mytrace *t, 
    4040                              long dest, char const *src, size_t n); 
    41 static long remote_syscall(pid_t pid, long call, 
     41static long remote_syscall(struct mytrace *t, long call, 
    4242                           long arg1, long arg2, long arg3); 
    4343#   if defined DEBUG 
     
    5353#define SYSCALL_X86   0x80cd  /* CD 80 = int $0x80 */ 
    5454#define SYSCALL_AMD64 0x050fL /* 0F 05 = syscall */ 
    55  
    56 #define MYCALL_OPEN     0 
    57 #define MYCALL_CLOSE    1 
    58 #define MYCALL_WRITE    2 
    59 #define MYCALL_DUP2     3 
    60 #define MYCALL_SETPGID  4 
    61 #define MYCALL_SETSID   5 
    62 #define MYCALL_KILL     6 
    6355 
    6456#if defined __x86_64__ 
     
    8476#endif 
    8577 
     78#define MYCALL_OPEN     0 
     79#define MYCALL_CLOSE    1 
     80#define MYCALL_WRITE    2 
     81#define MYCALL_DUP2     3 
     82#define MYCALL_SETPGID  4 
     83#define MYCALL_SETSID   5 
     84#define MYCALL_KILL     6 
     85#define MYCALL_FORK     7 
     86#define MYCALL_EXIT     8 
     87 
    8688#if defined __x86_64__ 
     89/* from unistd_32.h on an amd64 system */ 
     90int syscalls32[] = { 5, 6, 4, 63, 57, 66, 37, 2, 1 }; 
     91int syscalls64[] = 
     92#else 
    8793int syscalls32[] = 
    88     { 5, 6, 4, 63, 57, 66, 37 }; /* from unistd_32.h on an amd64 system */ 
    89 int syscalls64[] = 
    90 #else 
    91 int syscalls32[] = 
    9294#endif 
    9395    { SYS_open, SYS_close, SYS_write, SYS_dup2, SYS_setpgid, SYS_setsid, 
    94       SYS_kill }; 
     96      SYS_kill, SYS_fork, SYS_exit }; 
     97 
     98char const *syscallnames[] = 
     99    { "open", "close", "write", "dup2", "setpgid", "setsid", "kill", "fork", 
     100      "exit" }; 
    95101 
    96102struct mytrace 
    97103{ 
    98     pid_t pid; 
     104    pid_t pid, child; 
    99105}; 
    100106 
     
    103109#if defined USE_GRAB 
    104110    struct mytrace *t; 
     111    int status; 
    105112 
    106113    if(ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) 
     
    109116        return NULL; 
    110117    } 
    111     waitpid(pid, NULL, 0); 
     118    if(waitpid(pid, &status, 0) < 0) 
     119    { 
     120        perror("waitpid"); 
     121        return NULL; 
     122    } 
     123    if(!WIFSTOPPED(status)) 
     124    { 
     125        fprintf(stderr, "traced process was not stopped\n"); 
     126        ptrace(PTRACE_DETACH, pid, 0, 0); 
     127        return NULL; 
     128    } 
    112129 
    113130    t = malloc(sizeof(struct mytrace)); 
    114131    t->pid = pid; 
     132    t->child = 0; 
    115133 
    116134    return t; 
     135#else 
     136    errno = ENOSYS; 
     137    return NULL; 
     138#endif 
     139} 
     140 
     141struct mytrace* mytrace_fork(struct mytrace *t) 
     142{ 
     143#if defined USE_GRAB 
     144    struct mytrace *child; 
     145 
     146    ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEFORK); 
     147    remote_syscall(t, MYCALL_FORK, 0, 0, 0); 
     148    waitpid(t->child, NULL, 0); 
     149 
     150    child = malloc(sizeof(struct mytrace)); 
     151    child->pid = t->child; 
     152    child->child = 0; 
     153 
     154    return child; 
    117155#else 
    118156    errno = ENOSYS; 
     
    128166 
    129167    return 0; 
     168#else 
     169    errno = ENOSYS; 
     170    return -1; 
     171#endif 
     172} 
     173 
     174long mytrace_getpid(struct mytrace *t) 
     175{ 
     176#if defined USE_GRAB 
     177    return t->pid; 
    130178#else 
    131179    errno = ENOSYS; 
     
    154202    memcpy_into_target(t, regs.RSP, path, size); 
    155203 
    156     ret = remote_syscall(t->pid, MYCALL_OPEN, regs.RSP, O_RDWR, 0755); 
     204    ret = remote_syscall(t, MYCALL_OPEN, regs.RSP, O_RDWR, 0755); 
    157205 
    158206    /* Restore the data */ 
     
    175223{ 
    176224#if defined USE_GRAB 
    177     return remote_syscall(t->pid, MYCALL_CLOSE, fd, 0, 0); 
     225    return remote_syscall(t, MYCALL_CLOSE, fd, 0, 0); 
    178226#else 
    179227    errno = ENOSYS; 
     
    203251    memcpy_into_target(t, regs.RSP, data, len); 
    204252 
    205     ret = remote_syscall(t->pid, MYCALL_WRITE, fd, regs.RSP, len); 
     253    ret = remote_syscall(t, MYCALL_WRITE, fd, regs.RSP, len); 
    206254 
    207255    /* Restore the data */ 
     
    224272{ 
    225273#if defined USE_GRAB 
    226     return remote_syscall(t->pid, MYCALL_DUP2, oldfd, newfd, 0); 
     274    return remote_syscall(t, MYCALL_DUP2, oldfd, newfd, 0); 
    227275#else 
    228276    errno = ENOSYS; 
     
    234282{ 
    235283#if defined USE_GRAB 
    236     return remote_syscall(t->pid, MYCALL_SETPGID, pid, pgid, 0); 
     284    return remote_syscall(t, MYCALL_SETPGID, pid, pgid, 0); 
    237285#else 
    238286    errno = ENOSYS; 
     
    244292{ 
    245293#if defined USE_GRAB 
    246     return remote_syscall(t->pid, MYCALL_SETSID, 0, 0, 0); 
     294    return remote_syscall(t, MYCALL_SETSID, 0, 0, 0); 
    247295#else 
    248296    errno = ENOSYS; 
     
    254302{ 
    255303#if defined USE_GRAB 
    256     return remote_syscall(t->pid, MYCALL_KILL, pid, sig, 0); 
     304    return remote_syscall(t, MYCALL_KILL, pid, sig, 0); 
     305#else 
     306    errno = ENOSYS; 
     307    return -1; 
     308#endif 
     309} 
     310 
     311int mytrace_exit(struct mytrace *t, int status) 
     312{ 
     313#if defined USE_GRAB 
     314    ptrace(PTRACE_SETOPTIONS, t->pid, NULL, PTRACE_O_TRACEEXIT); 
     315    return remote_syscall(t, MYCALL_EXIT, status, 0, 0); 
    257316#else 
    258317    errno = ENOSYS; 
     
    333392} 
    334393 
    335 static long remote_syscall(pid_t pid, long call, 
    336                             long arg1, long arg2, long arg3) 
     394static long remote_syscall(struct mytrace *t, long call, 
     395                           long arg1, long arg2, long arg3) 
    337396{ 
    338397    /* Method for remote syscall: 
     
    347406    int bits; 
    348407 
    349 print_registers(pid); 
     408    if(call < 0 || call >= (long)(sizeof(syscallnames)/sizeof(*syscallnames))) 
     409    { 
     410        fprintf(stderr, "unknown remote syscall %li\n", call); 
     411        return -1; 
     412    } 
     413 
     414    debug("remote syscall %s(%lu, %lu, %lu)", 
     415          syscallnames[call], arg1, arg2, arg3); 
     416 
     417    print_registers(t->pid); 
     418 
    350419#if defined __x86_64__ 
    351420    bits = 64; 
     
    356425    for(;;) 
    357426    { 
    358         if(ptrace(PTRACE_GETREGS, pid, NULL, &oldregs) < 0) 
     427        if(ptrace(PTRACE_GETREGS, t->pid, NULL, &oldregs) < 0) 
    359428        { 
    360429            fprintf(stderr, "PTRACE_GETREGS failed\n"); 
     
    362431        } 
    363432 
    364         oinst = ptrace(PTRACE_PEEKTEXT, pid, oldregs.RIP - 2, 0) & 0xffff; 
     433        oinst = ptrace(PTRACE_PEEKTEXT, t->pid, oldregs.RIP - 2, 0) & 0xffff; 
    365434 
    366435#if defined __x86_64__ 
     
    377446#endif 
    378447 
    379         if(ptrace(PTRACE_SYSCALL, pid, NULL, 0) < 0) 
     448        if(ptrace(PTRACE_SYSCALL, t->pid, NULL, 0) < 0) 
    380449        { 
    381450            perror("ptrace_syscall (1)"); 
    382451            return -1; 
    383452        } 
    384         waitpid(pid, NULL, 0); 
    385  
    386         if(ptrace(PTRACE_SYSCALL, pid, NULL, 0) < 0) 
     453        waitpid(t->pid, NULL, 0); 
     454 
     455        if(ptrace(PTRACE_SYSCALL, t->pid, NULL, 0) < 0) 
    387456        { 
    388457            perror("ptrace_syscall (2)"); 
    389458            return -1; 
    390459        } 
    391         waitpid(pid, NULL, 0); 
    392     } 
    393  
    394     print_registers(pid); 
     460        waitpid(t->pid, NULL, 0); 
     461    } 
     462 
     463    print_registers(t->pid); 
    395464 
    396465    regs = oldregs; 
     
    413482    } 
    414483 
    415     if(ptrace(PTRACE_SETREGS, pid, NULL, &regs) < 0) 
     484    if(ptrace(PTRACE_SETREGS, t->pid, NULL, &regs) < 0) 
    416485    { 
    417486        fprintf(stderr, "PTRACE_SETREGS failed\n"); 
     
    419488    } 
    420489 
    421     print_registers(pid); 
    422  
    423     if(ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) 
    424     { 
    425         fprintf(stderr, "PTRACE_SINGLESTEP failed\n"); 
    426         return -1; 
    427     } 
    428     waitpid(pid, NULL, 0); 
    429  
    430     print_registers(pid); 
    431  
    432     if(ptrace(PTRACE_GETREGS, pid, NULL, &regs) < 0) 
     490    for(;;) 
     491    { 
     492        int status; 
     493 
     494        print_registers(t->pid); 
     495 
     496        if(ptrace(PTRACE_SINGLESTEP, t->pid, NULL, NULL) < 0) 
     497        { 
     498            fprintf(stderr, "PTRACE_SINGLESTEP failed\n"); 
     499            return -1; 
     500        } 
     501        waitpid(t->pid, &status, 0); 
     502 
     503        if(WIFEXITED(status)) 
     504            return 0; 
     505 
     506        if(!WIFSTOPPED(status) || WSTOPSIG(status) != SIGTRAP) 
     507            continue; 
     508 
     509        /* Fuck Linux: there is no macro for this */ 
     510        switch((status >> 16) & 0xffff) 
     511        { 
     512        case PTRACE_EVENT_FORK: 
     513            if(ptrace(PTRACE_GETEVENTMSG, t->pid, 0, &t->child) < 0) 
     514            { 
     515                fprintf(stderr, "PTRACE_GETEVENTMSG failed\n"); 
     516                return -1; 
     517            } 
     518            continue; 
     519        case PTRACE_EVENT_EXIT: 
     520            /* The process is about to exit, don't do anything else */ 
     521            return 0; 
     522        } 
     523 
     524        break; 
     525    } 
     526 
     527    print_registers(t->pid); 
     528 
     529    if(ptrace(PTRACE_GETREGS, t->pid, NULL, &regs) < 0) 
    433530    { 
    434531        fprintf(stderr, "PTRACE_GETREGS failed\n"); 
     
    436533    } 
    437534 
    438     if(ptrace(PTRACE_SETREGS, pid, NULL, &oldregs) < 0) 
     535    if(ptrace(PTRACE_SETREGS, t->pid, NULL, &oldregs) < 0) 
    439536    { 
    440537        fprintf(stderr, "PTRACE_SETREGS failed\n"); 
    441538        return -1; 
    442539    } 
    443     print_registers(pid); 
    444  
    445     debug("syscall %ld returned %ld", call, regs.RAX); 
     540    print_registers(t->pid); 
     541 
     542    debug("syscall %s returned %ld", syscallnames[call], regs.RAX); 
    446543 
    447544    if((long)regs.RAX < 0) 
Note: See TracChangeset for help on using the changeset viewer.