Как получить многопоточное приложение? - PullRequest
6 голосов
/ 29 марта 2011

РЕДАКТИРОВАТЬ (MADE PROGRESS):

Я пытаюсь найти демона vsftpd. У меня есть следующий код, который присоединяется к демону. Затем он успешно отображает PID первого порожденного процесса. Тем не менее, для детей этого порожденного процесса он возвращает PID как 2,3, ... Программа действительно улавливает завершение порожденных процессов, что заставляет меня думать, что я близок.

Есть идеи?

void * trace_process(void * pid){
    pid_t child = atoi((char *) pid);
    long orig_eax, eax;
    int status;
    int callmade = FALSE;
    long opt = PTRACE_O_TRACEFORK;
    long newpid;

    long trace = ptrace(PTRACE_ATTACH,child,NULL,NULL);
    ptrace(PTRACE_SETOPTIONS,child,NULL,opt);
    if(trace == FALSE)
        printf("Attached to %d\n",child);

    while(TRUE) {
        child = waitpid(-1, &status, __WALL);

        if (status >> 16 == PTRACE_EVENT_FORK) {
            ptrace(PTRACE_GETEVENTMSG, child, NULL, (long) &newpid);
            ptrace(PTRACE_SYSCALL, newpid, NULL, NULL);       

            printf("Attached to offspring %ld\n", newpid);  
        }
        else{
            if(WIFEXITED(status))
                printf("Child %d exited\n", child);
        }

        ptrace(PTRACE_SYSCALL,child, NULL, NULL);
    }  
}

Пример вывода:

Attached to 2015 // daemon
Attached to offspring 5302 // new connection handler
Attached to offspring 2 // should be authenticator
Child 5303 exited       // authenticator exiting on successful login
Attached to offspring 3 // should be process serving files
Child 5304 exited       // logout: process serving files
Child 5302 exited       // connection closed
Attached to offspring 5305 // new connection handler
Attached to offspring 2    // ... repeat
Child 5306 exited
Attached to offspring 3
Child 5307 exited
Child 5305 exited

Ответы [ 3 ]

1 голос
/ 31 марта 2011

Пройдя дальше с моим кодом, я понимаю, что он действительно работает для захвата всех системных вызовов, поступающих от родителя и его потомков. Единственная проблема заключается в том, что идентификаторы PID возвращаются как относительные числа, а не как действительные идентификаторы. Это приводит к тому, что вы не уверены, что PID ожидания был сгенерирован из родительского объекта. В любом случае, код получит все системные вызовы. Я все еще хотел бы знать, почему PID является относительным, насколько мне известно, но код работает нормально.

1 голос
/ 23 мая 2012

Пусть поток будет запущен до следующего wait().

Попробуйте:

ptrace(PTRACE_SYSCALL,child, NULL, NULL);

До:

while(TURE)
1 голос
/ 30 марта 2011

Читая статью Игра с ptrace , я нашел этот комментарий от пользователя, который также боролся с этим:

/* After struggled a long time, I got a true way to make my ptrace worked 
 * correct with multi-thread application. Here're my sample codes, hope it 
 * can help others whom have the same confusion. */    

char trapCode[] = {0, 0, 0, 0};
int status;

ptrace(PTRACE_ATTACH, childProcess, NULL, NULL); //childProcess is the main thread
wait(NULL);

printf("\nchild %d created\n", childProcess);
fflush(stdout);

long ptraceOption = PTRACE_O_TRACECLONE;
ptrace(PTRACE_SETOPTIONS, childProcess, NULL, ptraceOption);

struct user_regs_struct regs;

for(unsigned int i = 0; i < m_breakPoints.size(); i++)
{
    BreakPoint_Info breakPointInfo = m_breakPoints[i];
    if(!breakPointInfo.m_enabled)
        continue;

    unsigned int index = breakPointInfo.m_checkPointIndex;
    if(m_bytesBackup.find(m_checkPoints[index].m_offset) != m_bytesBackup.end())
        continue;

    unsigned long readAddr = m_checkPoints[index].m_offset;
    One_Byte_With_Result *oneByte = new One_Byte_With_Result;
    getData(childProcess, readAddr, trapCode, 4);
    oneByte->m_char = trapCode[0];
    trapCode[0] = 0xcc;
    putData(childProcess, readAddr, trapCode, 4);

    m_bytesBackup.insert(std::make_pair(m_checkPoints[index].m_offset, oneByte));
}

std::set allThreads;
std::set::iterator allThreadsIter;
allThreads.insert(childProcess);

int rec = ptrace(PTRACE_CONT, childProcess, NULL, NULL);

while(true)
{
    pid_t child_waited = waitpid(-1, &status, __WALL);

    if(child_waited == -1)
        break;

    if(allThreads.find(child_waited) == allThreads.end())
    {
        printf("\nreceived unknown child %d\t", child_waited);
        break;
    }

    if(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP)
    {
        pid_t new_child;
        if(((status >> 16) & 0xffff) == PTRACE_EVENT_CLONE)
        {
            if(ptrace(PTRACE_GETEVENTMSG, child_waited, 0, &new_child) != -1)
            {        
                allThreads.insert(new_child);
                ptrace(PTRACE_CONT, new_child, 0, 0);

                printf("\nchild %d created\t", new_child);
            }

            ptrace(PTRACE_CONT, child_waited, 0, 0);
            continue;
        }
    }

    if(WIFEXITED(status))
    {
        allThreads.erase(child_waited);
        printf("\nchild %d exited with status %d\t", child_waited, WEXITSTATUS(status));

        if(allThreads.size() == 0)
            break;
    }
    else if(WIFSIGNALED(status))
    {
        allThreads.erase(child_waited);
        printf("\nchild %d killed by signal %d\t", child_waited, WTERMSIG(status));

        if(allThreads.size() == 0)
            break;
    }
    else if(WIFSTOPPED(status))
    {
        int stopCode = WSTOPSIG(status);
        if(stopCode == SIGTRAP)
        {
            ptrace(PTRACE_GETREGS, child_waited, NULL, &regs);
            unsigned long currentEip = regs.eip;
            //printf("%d\t%08x\n", child_waited, currentEip);

            Address_Bytes_Map::iterator iter = m_bytesBackup.find(currentEip - 1);
            if(iter != m_bytesBackup.end())
            {
                iter->second->m_result = true;

                regs.eip = regs.eip - 1;
                getData(child_waited, regs.eip, trapCode, 4);
                trapCode[0] = iter->second->m_char;
                putData(child_waited, regs.eip, trapCode, 4);
                rec = ptrace(PTRACE_SETREGS, child_waited, NULL, &regs);
            }
        }
    }

    rec = ptrace(PTRACE_CONT, child_waited, 1, NULL);

    continue;
}
...