2011-03-29 5 views
5

EDIT (MADE PROGRESS) :멀티 스레드 응용 프로그램을 ptrace하는 방법은 무엇입니까?

vsftpd 데몬을 ptrace하려고합니다. 나는 데몬에 붙어있는 다음 코드를 가지고있다. 그런 다음 첫 번째 생성 된 프로세스의 PID를 성공적으로 표시합니다. 그러나이 생성 된 프로세스의 하위 항목에 대해 2,3,3 ... PID를 반환합니다. 프로그램이 생성 된 프로세스의 종료를 catch하지만 내가 가까이에 있다고 생각하게 만듭니다.

아이디어가 있으십니까?

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 
+0

당신이 strace를 (1)'로 봤어'전혀? –

+0

@ Nikolai N Fetissov 지금 strace 소스를 조사 중입니다. 그렇게하기가 쉽지는 않습니다. 더 흥미로운 점은 내가 strace를 vsftpd의 pid에 연결했고 ncftp를 사용하여 로그인하면 "연결 중 ..."대화 상자에 멈추는 것입니다. strace에서 Ctrl-c를 누르면 제대로 작동합니다. strace도 실제로 작동하지 않습니다. – ofosho

+0

'-f' 옵션을 사용 했습니까? –

답변

1

I 부모와 자식으로부터 오는 모든 시스템 호출을 캡처하는 것이 실제로 작동한다는 것을 깨닫게됩니다. 유일한 문제는 PID가 실제 PI가 아닌 상대 번호로 반환된다는 것입니다. 그 결과 대기 PID가 실제로 부모로부터 생성되었다는 것을 확신하지 못하게됩니다. 어쨌든 코드는 모든 시스템 호출을 가져옵니다. PID가 왜 상대적인지를 알고 싶습니다.하지만 코드는 잘 작동합니다.

+0

그들은 상대 PID가 아니며 새로운 PID 네임 스페이스 (다시 1에서 시작)에있는 PID입니다. 사실 현재 straplce 소스에 심대한 손상을 입히고 있습니다. –

0

Playing with ptrace 기사를 읽는 동안, 나는이 고생 사용자로부터 this comment를 발견, 내 코드를 더 진행 한 후

/* 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; 
} 
+0

그래, 그거 내가 기반으로하는 코드 야. 나는 기본적으로 같은 것을 가지고 있지만 게시 목적으로 단순화했습니다. 그의 버전을 직접 사용할 때 "알 수없는 아이"가 나오고 종료됩니다. 이는 저장되어 (2,3, ..) 빠져 나올 때 실제 pid를 받았기 때문에 의미가 있습니다. 나는 그 게시물을 고맙게 생각한다. – ofosho

+0

@ofosho 좋아, 나중에 살펴 보겠습니다. – karlphillip

1

스레드가 다음 wait() 전에 실행되도록하십시오.

시도 :

ptrace(PTRACE_SYSCALL,child, NULL, NULL); 

전 :

while(TURE) 
관련 문제