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.