3

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.

Muhammad Waqar
  • 849
  • 2
  • 13
  • 29

1 Answers1

0

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.

ugoren
  • 16,023
  • 3
  • 35
  • 65
  • I don't think the line you mentioned is the problem. The reply received is of the form `IP|port` (`NAT_VM_DELIMITER` is a character '|'). I have to separate these. If that statement was the problem, then line `fprintf(stderr, "[LD_INTERPOSER] IP[%s], Port[%d] for VM[%s]\n", ip_address, tport, vm_ip);` would not have printed correct (separate) IP and port. Also, I think if that statement was the problem, program would have terminated there instead of working till the second-last statement `fprintf(stderr, "Done\n");` of the function. – Muhammad Waqar Jun 26 '12 at 09:58
  • 1
    Maybe this isn't what caused the problem, but it is a bug. You should start by fixing the two bugs I showed you, and then try to debug it. – ugoren Jun 26 '12 at 11:16
  • I have rectified all the bugs you mentioned. Still the same `*** stack smashing detected ***` output. – Muhammad Waqar Jun 28 '12 at 07:51