5

ptraceプログラムによって生成されたプログラムがどのシステムコールを呼び出すかを確認するために使用したいと思います。以前の質問への回答で説明されていたので、このチュートリアルから始めました。使用しているプラ​​ットフォーム(SLES 11 64ビット)にコードを適合させてコードを変更し、生成されたプロセスが行うすべてのシステムコールを出力する次のテストコードをまとめました。

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/reg.h>
#include <sys/syscall.h>   /* For SYS_write etc */

pid_t child;

void run()
{
    long orig_eax;
    int status;

     while(1) {
          int pid = wait(&status);
          if (pid == -1) {
              perror("wait");
              kill(child, SIGKILL);
              return;
          }
          printf("Got event from %d.\n", pid);
          if(WIFEXITED(status))
              break;
          orig_eax = ptrace(PTRACE_PEEKUSER,
                     pid, 8 * ORIG_RAX, NULL);
          if (orig_eax == -1) {
              perror("ptrace");
              kill(child, SIGKILL);
              return;
          } else {
              printf("Syscall %ld called.\n", orig_eax);
          }
            ptrace(PTRACE_SYSCALL,
                   pid, NULL, NULL);
    }
}

int main(int /*argc*/, char* argv[])
{

    child = fork();
    if(child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl(argv[1], argv[1], NULL);
    }
    else {
        printf("Child process id = %d.\n", child);
        run();

    }
    return 0;
}

これは非常にうまく機能します。プログラムによって行われたシステムコールのIDを出力します(実際には、それぞれを2回出力します。1回は開始時、もう1回は終了時ですが、今は問題ではありません)。ただし、私のプログラムはシステムコールのチェック以外のことを行う必要があるため、チェックを別のスレッドに移動することにしました(CよりもC ++の方が快適なので、C ++の方法で行いましたが、それは重要だとは思わないでください)。もちろん、この最初のプログラムでは、スレッドを開始してから参加するだけです。

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/reg.h>
#include <sys/syscall.h>   /* For SYS_write etc */

#include <boost/thread.hpp>


pid_t child;

void run()
{
    long orig_eax;
    int status;

     while(1) {
          int pid = wait(&status);
          if (pid == -1) {
              perror("wait");
              kill(child, SIGKILL);
              return;
          }
          printf("Got event from %d.\n", pid);
          if(WIFEXITED(status))
              break;
          orig_eax = ptrace(PTRACE_PEEKUSER,
                     pid, 8 * ORIG_RAX, NULL);
          if (orig_eax == -1) {
              perror("ptrace");
              kill(child, SIGKILL);
              return;
          } else {
              printf("Syscall %ld called.\n", orig_eax);
          }
            ptrace(PTRACE_SYSCALL,
                   pid, NULL, NULL);
    }
}

int main(int /*argc*/, char* argv[])
{

    child = fork();
    if(child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl(argv[1], argv[1], NULL);
    }
    else {
        printf("Child process id = %d.\n", child);
        boost::thread t(run);
        t.join();
    }
    return 0;
}

今回はエラーメッセージが表示されます。

Child process id = 24682.
Got event from 24682.
ptrace: No such process

どうしてこれなの?答えを探してみましたが、こんなものは見つかりませんでした。子プロセスによって開始されたスレッドをトレースしないことがわかりましたptraceが、それは後で処理する必要がある別のことです。別のセラドから子プロセスをチェックすることさえ可能ですか?

もう1つの奇妙なことは、実際のアプリケーションでは基本的に同じことを実行し(ただし、クラス、ミューテックスなど、はるかに複雑なコンテキストから)、異なる種類のエラーが発生することです。ptraceエラーで戻る代わりにwait、子プロセスのシステムコールに対しても戻りません(そして子プロセスは停止しません)。一方、wait子プロセスが終了すると、期待どおりに機能します。

4

1 に答える 1

1

私が知る限り、ptraceプロセスごとに1つのトレーサーのみを許可します。これは、アタッチしようとすると、強制的にアタッチしようとすると、指定されたプロセスにアタッチできなかったことをPTRACE_ATTACH示すエラーが表示されることを意味します。ptrace

したがって、スレッドが子プロセスに接続されていないためにエラーが表示されます。このようにしようとするptraceと、失敗してコードが送信され-ESRCHます。

さらに、ここでこの投稿を見ることができます。これとは別に、他のいくつかの質問に答えることができます。

于 2012-11-15T10:46:11.890 に答える