2012-06-26 75 views
2

我正在編寫Java中介層以修改與網絡通信相關的系統調用。基本上,我想修改預期收件人的IP和端口。在Java插入程序中堆棧碎片

的代碼工作正常在我的筆記本電腦,但大學的電腦上,它提供了堆棧溢出錯誤爲:

*** stack smashing detected ***: java terminated 
======= Backtrace: ========= 
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7702dd5] 
/lib/i386-linux-gnu/libc.so.6(+0xffd8a)[0xb7702d8a] 
/home/mwaqar/vibe/ldinterposer_2.so(+0x28e4)[0xb77c98e4] 
/home/mwaqar/vibe/ldinterposer_2.so(connect+0x9c5)[0xb77c9093] 
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/libnet.so(+0xceff)[0x8b226eff] 
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/libnet.so(Java_java_net_PlainSocketImpl_socketConnect+0x4c1)[0x8b227c51] 

相關的代碼(的插入連接系統調用)如下:

int connect(int fd, const struct sockaddr *sk, socklen_t sl) 
{ 
struct sockaddr_in  *lsk_in = (struct sockaddr_in *) sk; 
struct sockaddr_in6  *lsk_in6 = (struct sockaddr_in6 *) sk; 

struct sockaddr_in  addr4; 

unsigned int   len; 
int      nbytes, oport, tport, ret, i; 
char     ip_address[30]; 
char     buffer[1024]; 
char     tempBuffer[1024]; 

if((lsk_in->sin_family == AF_INET) || (lsk_in->sin_family == AF_INET6)) 
{ 
    if(lsk_in->sin_family == AF_INET) 
    { 
     oport = ntohs(lsk_in->sin_port); 
     memcpy(&addr4.sin_addr.s_addr, &lsk_in->sin_addr.s_addr, sizeof(addr4.sin_addr.s_addr)); 
    } 
    else if(lsk_in->sin_family == AF_INET6) 
    { 
     oport = ntohs(lsk_in6->sin6_port); 
     memcpy(&addr4.sin_addr.s_addr, lsk_in6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr)); 
    } 

    memset(buffer, '\0', sizeof(buffer)); 
    sprintf(buffer, "%s%c%s%c%i", NAT_VM_CONNECT_RULE, NAT_VM_DELIMITER, (char *)inet_ntoa(addr4.sin_addr), NAT_VM_DELIMITER, oport); 

    nbytes = send(sock, buffer, strlen(buffer), 0); 
    if(DEBUG_MODE) 
     fprintf(stdout, "[LD_INTERPOSER] Sent[%s]\n", buffer); 

    memset(buffer, '\0', sizeof(buffer)); 
    nbytes = recv(sock, buffer, sizeof(buffer), 0); 

    fprintf(stderr, "[LD_INTERPOSER] Received CONNECT [%s]\n", buffer); 

    memset(ip_address, '\0', sizeof(ip_address)); 
    int pos = strrchr(buffer, NAT_VM_DELIMITER) - buffer; 

    strncpy(ip_address, buffer, pos); 
    ip_address[pos] = '\0'; 
    tport = atoi(buffer + pos + 1); 

    if(lsk_in->sin_family == AF_INET) 
    { 
     lsk_in->sin_addr.s_addr = inet_addr(ip_address + 7); 
     lsk_in->sin_port = htons(tport); 
    } 
    else if(lsk_in->sin_family == AF_INET6) 
    { 
     inet_pton(AF_INET6, ip_address, &(lsk_in6->sin6_addr)); 
     lsk_in6->sin6_port = htons(tport); 
    } 

    fprintf(stderr, "[LD_INTERPOSER] IP[%s], Port[%d] for VM[%s]\n", ip_address, tport, vm_ip); 
} 

int my_ret = real_connect(fd, sk, sl); 
fprintf(stderr, "Done\n"); 
return my_ret; 
} 

這裏,襪子的是,我在共享庫的「構造」已初始化的插座。

該程序正常工作並打印完成。在最後一個(返回)行中,它給出堆棧粉碎錯誤。我不知道是什麼導致了這一點。

+0

聲明緩衝區在哪裏? – hmjd

+0

對不起,更新了代碼。 –

+0

堆棧粉碎錯誤是由檢查可能的緩衝區溢出錯誤的內置機制引起的。檢查你是否永遠不會寫更多的字節到'buffer'或'tempBuffer'它們的大小。 – buc

回答

0

我懷疑strrcr回報NULL在該行

int pos = strrchr(buffer, NAT_VM_DELIMITER) - buffer; 

然後pos將是巨大的,而其後的行讀寫無效的地址。

總是檢查函數的返回值(特別是當它們在從程序外部接收的數據上運行時)。

此外,正如我在我的評論中寫的,從來沒有使用sprintf。我不知道它是否失敗,因爲我不知道NAT_VM_CONNECT_RULE是什麼。即使您計算了字節數並知道您沒有問題,您仍然應該小心並使用snprintf代替。

+0

我不認爲你提到的線是問題。收到的答覆是'IP | port'形式('NAT_VM_DELIMITER'是一個字符'|')。我必須分開這些。如果這個聲明是問題,那麼在'fprintf(stderr,「[LD_INTERPOSER] IP [%s],VM [%s]的端口[%d] \ n」,ip_address,tport,vm_ip)打印正確(單獨)的IP和端口。另外,我認爲如果這個陳述是問題的話,那麼程序就會在那裏終止,而不是直到倒數第二個陳述'fprintf(stderr,「Done \ n」);'這個函數。 –

+0

也許這不是造成問題的原因,但它是一個錯誤。您應該先解決我向您展示的兩個錯誤,然後嘗試調試它。 – ugoren

+0

我已經糾正了您提到的所有錯誤。 *** ***檢測***'輸出仍然是相同的。 –