web-dev-qa-db-ja.com

Valgrindが初期化されていないバイトについて叫ぶ

Valgrindは私にこのエラーをスローします:

==11204== Syscall param write(buf) points to uninitialised byte(s)
==11204==    at 0x4109033: write (in /lib/libc-2.13.so)
==11204==    by 0x8049654: main (mmboxman.c:289)
==11204==  Address 0xbe92f861 is on thread 1's stack
==11204== 

どうしたの?初期化されていないバイトが何を叫んでいるかわかりません。ここにコードの犯罪的な行があります(前述の289行は関数lockUpを呼び出す行です):

Request request;            
Response response;              

fillRequest(&request, MANADDUSER, getpid(), argument1, NULL, NULL, 0, 0);
lockUp(&request, &response, NULL);

ここで関数プロトタイプと構造体宣言:

void fillRequest(Request *request, char code, pid_t pid, char *name1, char *name2, char   *object, int id, size_t size)
{
    int k;

    request->code = code;
    request->pid = getpid();

    if(name1)    for(k=0; k<strlen(name1)+1; k++)   request->name1[k] = name1[k];
    else         request->name1[0] = '\0';

    if(name2)    for(k=0; k<strlen(name2)+1; k++)   request->name2[k] = name2[k];
    else         request->name2[0] = '\0';  

    if(object)   for(k=0; k<strlen(name2)+1; k++)   request->name2[k] = name2[k];
    else         request->object[0] = '\0'; 

    request->id    = id;
    request->size = size;
}

void lockUp(Request *request, Response *response, void **buffer)
{
    int fifofrom, fifoto, lock;     /* file descriptor delle fifo e del lock */

    /* locko per l'accesso alle FIFO */
    if((lock = open(LOCK, O_RDONLY)) == -1)   logMmboxman("error in opening LOCK\n", 1);
    else                                      logMmboxman("opened LOCK\n", 0);

    if(flock(lock, LOCK_EX) == -1)            logMmboxman("error in acquiring LOCK\n", 1);              
    else                                              logMmboxman("acquired LOCK\n", 0);  

    /* apro la fifoto e scrivo la mia richiesta */
    if((fifoto = open(FIFOTOMMBOXD, O_WRONLY)) == -1)   logMmboxman("error in opening FIFOTO\n", 1); 
    else                                                logMmboxman("opened FIFOTO\n", 0);  

    if((write(fifoto, request, sizeof(Request))) != sizeof(Request))   logMmboxman("error in writing FIFOTO\n", 1);
    else                                                               logMmboxman("written on FIFOTO\n", 0);
    close(fifoto);

    /* rimango in attesa della risposta da mmboxd sulla fifofrom */
    if((fifofrom = open(FIFOFROMMMBOXD, O_RDONLY)) == -1)   logMmboxman("error in opening FIFOFROM\n", 1);
    else                                                    logMmboxman("opened FIFOFROM\n", 0);

    if((read(fifofrom, response, sizeof(Response))) != sizeof(Response))   logMmboxman("error in reading FIFOFROM\n", 1);
    else                                                                   logMmboxman("read from FIFOFROM\n", 0);
    close(fifofrom);

    /* se mi deve comunicare un buffer riapro la fifo e lo leggo */
    if(response->size)
    {
            if((fifofrom = open(FIFOFROMMMBOXD, O_RDONLY)) == -1)   logMmboxman("error in opening FIFOFROM again for the buffer\n", 1);
            else                                                    logMmboxman("opened FIFOFROM again for the buffer\n", 0);

            *buffer = (void*)malloc(response->size);

            if(read(fifofrom, *buffer, response->size) != response->size)   logMmboxman("error in reading FIFOFROM again for the buffer\n", 1);
            else                                                            logMmboxman("read from FIFOFROM again for the buffer\n", 0);
            close(fifofrom);    
    }

    /* letta la risposta rilascio il lock */
    if(flock(lock, LOCK_UN) == -1)            logMmboxman("error in releasing LOCK\n", 1);              
    else                                      logMmboxman("released LOCK\n", 0);  

    return;
}

typedef struct 
{
    char code;          
    pid_t pid;          
    char name1[41];     
    char name2[41];     
    char object[101];   
    int id;             
    size_t size;        
} Request;

typedef struct 
{
    char result;    
    int num;        
    int num2;   
    size_t size;    
} Response;
26
Damiano Barbati

Request構造体には、ヌルで終了する文字列を含む配列name1name2などがあります。それらを埋めるとき、ヌルターミネーターを超えて書き込むことはありません。後でファイルに構造を書き込むと、これらのバイトが初期化されていないため、valgrindは文句を言います。その他の初期化されていないバイト(たとえば、コンパイラーによって挿入されたパディング)も存在する可能性があります。

これは、小さなセキュリティの問題以外は必ずしも問題ではありません。機密情報を保持している可能性のある以前のメモリの内容がファイルに書き込まれます。

このエラーを回避するために、フィールドに入力する前に構造を0にmemsetできます。

41
interjay