Muhammad Waqar
Muhammad Waqar

Reputation: 879

Stack Smashing in Java Interposer

I am writing a Java interposer to modify network communication related system calls. Basically, I want to modify the IP and port of the intended recipient.

The code works correctly on my laptop, but on university PC, it gives a stack smashing error as:

*** 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]

The relevant code (interposition of connect system call) is as follows:

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;
}

Here, sock is a socket that I have initialized in "constructor" of the shared library.

The program works correctly and prints Done. On the last (return) line, it gives the stack smashing error. I have no idea what is causing this.

Upvotes: 3

Views: 1102

Answers (1)

ugoren
ugoren

Reputation: 16441

I suspect that strrcr returns NULL in the line

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

Then pos will be huge, and the following lines will read and write invalid addresses.

Always check the return value of functions (especially when they're run on data received from outside your program).

Also, as I wrote in my comment, never use sprintf. I can't tell if it fails, because I don't know what's NAT_VM_CONNECT_RULE. Even if you counted the bytes and know you're OK, you should still be careful and use snprintf instead.

Upvotes: 0

Related Questions