2013-01-01 9 views
5

みんな!私はこのようなプログラム(usemallocを)持っているLD_PRELOADedライブラリと子プロセス

画像:

#include <stdio.h> 
#include <stdlib.h> 

#define USER_BYTES_SIZE 100 

int main(void){ 
    char* userbytes = (char*)malloc(USER_BYTES_SIZE*sizeof(char)); 
    if(!userbytes) 
     return 1; 

    for(int i = 0; i <= USER_BYTES_SIZE; i++){ // "i <= USER_BYTES_SIZE" leads to an off-by-one memory overrun. 
     userbytes[i] = 0; 
    } 
    return 0; 
} 

あなたは、メモリのオーバーフローにつながるオフ対1のバグがあることがわかるよう

。実行時にこのようなバグを検出したい。 LD_PRELOADedライブラリは私の仕事を行うのに適しています。私はlibhijack.soというライブラリを作成して、実際のmalloc の呼び出しを乗っ取って、実際のmallocを呼び出して、実際のmallocでalloctされたメモリストリップの端に赤いゾーンを追加する私のカスタムmallocの呼び出しと置き換えました。このようなlibhijack.soのコード:

void* (*real_malloc) (size_t size); 
void* malloc(size_t size){ 
    real_malloc = ((void*)(*)(size_t))dlsym(RTLD_NEXT, "malloc"); 
    void* allocbytes = (void*)real_malloc(size + 4); //put 2 bytes at each end, call them red zones 
    return (allocbytes + 2); 
} 

私は、このコマンドを使用してライブラリとメインプログラムを実行します。メモリへのアクセスは、赤のゾーンに存在する場合、私はそれらを検出します次に

LD_PRELOAD=./libhijack.so ./usemalloc 

をし、メモリオーバーフローのバグとみなします。

このLD_PRELOADソリューションは、メインプロセスにmallocの呼び出しが含まれていても、フォークされた子プロセスがそれを実行すると失敗します。例えば

次のように、私たちは「usemalloc」を変更します。

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> // + 

#define USER_BYTES_SIZE 100 

int main(void){ 
    pid_t child = fork(); 
    if(child < 0) 
     exit(1); 

    if(child == 0){ //child process 
     char* userbytes = (char*)malloc(USER_BYTES_SIZE*sizeof(char)); 
     if(!userbytes) 
      return 1; 

     for(int i = 0; i <= USER_BYTES_SIZE; i++){ // "i <= USER_BYTES_SIZE" leads to an off-by-one memory overrun. 
      userbytes[i] = 0; 
     } 
    } 
    else { //the current process 
     wait(NULL); 
    } 
    return 0; 
} 

子プロセスで発生したオーバーフローのバグがLD_PRELOADedライブラリによって検出されることはありません。

私の質問は、LD_PRELOADedライブラリを使用して子プロセスのオーバーフローのバグを検出するにはどうすればいいですか?それは(LD_PRELOADedライブラリを使用して)可能ですか?そうでない場合、代替手段はありますか? 何か提案が評価されました!!!

+1

コンパイル時に 'valgrind'(&ASANオプション)を使用することを検討しましたか?これは、おそらくLDPRELOADというトリックを使わずに、すでに望むもののほとんどを提供します。 –

+0

valgrindまたはpinが私の計測には重すぎます。 LD_PRELOADのような軽量なソリューションが興味深い機能を乗っ取りたいだけです。とにかく、感謝のために感謝! –

+0

信頼性の高い軽量ソリューションはありません。そのようなバッファオーバーフローのバグに対するハードウェアの支援はなく、コンパイラにパッチを適用する必要があります。 ASANと最近のGCC(future 4.8)やClang(3.2)の最近の取り組みを参照してください。 –

答えて

0

libhijackコードが実際にメモリを割り当てていないことを指摘して私が嫌な気がすることはないと思いますか? pthread_mutex_lockはpthread_mutex_t *引数を必要とし、mutexロックが成功したかどうかにかかわらず成功/失敗を通知する整数を返します。

また、子プロセスをfork()していますが、これはスレッドを作成するのと少し異なります。したがって、pthread関数は実際にはあなたの後ろではないかもしれません...?

もう一つのトリックは、問題を引き起こしているコードが示されているが、どのように "赤いゾーン"をチェックしているかということです。おそらく、検出の奇跡は検出コードにあるでしょうか?

+0

編集のおかげで申し訳ありません。 dlsymの呼び出しでは、 "pthread_mutex_lock"を "malloc"に置き換える必要があります。私はそれを修正しました。私の質問は、LD_PRELOADedライブラリを使用して子プロセスのオーバーフローバグを検出する方法です。知っていますか? –

0

valgrindを使用してメモリリークやその他のメモリの問題を検出します。それは素晴らしい作品で、何も実装する必要はありません。

0

私はあなたの問題はfork()LD_PRELOADとは関係がありません。私はあなたのコードのどこかにバグかもしれないと思います。次のテストケースを使用して問題を再現しようとしました:

// preloadlib.c 
#define _GNU_SOURCE 
#include <dlfcn.h> 
#include <unistd.h> 
void* malloc(size_t size) 
{ 
     write(1, "malloc\n", 7); 
     void *(*real_malloc)(size_t) = dlsym(RTLD_NEXT, "malloc"); 
     return real_malloc(size); 
} 

// example.c 
#include <unistd.h> 
#include <stdlib.h> 
int main() 
{ 
     if (fork()) { 
       write(1, "A\n", 2); 
       malloc(1337); 
       write(1, "B\n", 2); 
     } else { 
       write(1, "C\n", 2); 
       malloc(1337); 
       write(1, "D\n", 2); 
     } 
     return 0; 
} 

# run.sh 
gcc -Wall -Wextra -o example example.c 
gcc -Wall -Wextra -fPIC -o preloadlib.so -shared preloadlib.c -ldl 
LD_PRELOAD=$PWD/preloadlib.so ./example 

そして、これは私が手に出力されます:

$ bash run.sh 
A 
malloc 
C 
B 
malloc 
D 

これは、64ビットのKubuntu 12.04(libcのバージョン2.15-0ubuntu10.4)です。

関連する問題