Random double free or invalid next_size

145 views Asked by At

So I'm having a problem right now with my program (well, more with the shared library I've written). I'm trying to implement a TCP/IP stack, and am currently trying to implement ARP. ARP works, both resolution and replies, however my ARP Server will randomly crash (sometimes running for 10-20min, being flooded with 40-50 arp requests a second) from a Double free() or invalid next_size (always on the rx_buff pointer).

When it fails, it always fails on the free in the last or second to last line.

Would anyone of you have any idea of why this is happening ? Gist here : https://gist.github.com/thehunt33r/651f76fe08ca06ec74ee

Edit : To the person that included the code in the edit, thanks :)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <stdint.h>
#include <errno.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>
//#include <net/if.h>
#include <netinet/ether.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <linux/netdevice.h>
#define ARP 1
/* Define structures */
typedef struct {
    uint8_t mac_dest[6];
    uint8_t mac_src[6];
    uint16_t ether_type;
} eth_header_t;
typedef struct {
    uint16_t hardware_type;
    uint16_t protocol_type;
    uint8_t hardware_l;
    uint8_t protocol_l;
    uint16_t operation;
    uint8_t sender_hwa[6];
    uint8_t sender_ip[4];
    uint8_t target_hwa[6];
    uint8_t target_ip[4];
} arp_header_t;
/* End Structures*/

eth_header_t parse_eth_header(uint8_t *buffer) { //parse eth header
    int i = 0;
    eth_header_t tmp;
    for (i = 0; i < 6; i++) {
        tmp.mac_dest[i] = buffer[i];
    }
    buffer += 6;
    for (i = 0; i < 6; i++) {
        tmp.mac_src[i] = buffer[i];
    }
    tmp.ether_type = (buffer[7] << 8) | buffer[6];
    uint8_t *tmp_8 = (uint8_t * ) & tmp.ether_type;
    tmp_8[0] = buffer[6];
    tmp_8[1] = buffer[7];

    return tmp;
}

/* Reading function */
int sup_read(int protocol, uint8_t *buffer, int buffer_length) {
    int s;
    s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (s == -1) {
        printf("Erreur lors de l'ouverture de la socket");
    }
    uint8_t *rx_buff = (uint8_t *) malloc(1500);
    int exit = 1;
    int length = 0;
    while (exit) {
        length = recvfrom(s, rx_buff, 65535, 0, NULL, NULL);
        uint8_t *tmp1 = rx_buff;
        eth_header_t tmp_head = parse_eth_header(rx_buff);
        eth_header_t *eth_head = &tmp_head;
        eth_head->ether_type = htons(eth_head->ether_type);
        switch (eth_head->ether_type) {
        case 0x0806:
            if (protocol == ARP) {
                tmp1 = rx_buff;
                tmp1 += sizeof(eth_header_t);
                length -=sizeof(eth_header_t);
                memcpy(buffer,rx_buff,length);
                printf("This is an ARP frame");
                exit=0;
            }
            break;
        }
    }
    close(s);
    free(rx_buff);
    return length;
}
/*End reading*/


int main(){
  uint8_t *buffer = (uint8_t *) malloc(1500);
  while(1){
     sup_read(1, buffer, sizeof(buffer));
}
}
1

There are 1 answers

0
Jonathan Leffler On BEST ANSWER

In sup_read(), you have:

uint8_t *rx_buff = (uint8_t *) malloc(1500);
int exit = 1;
int length = 0;
while (exit) {
    length = recvfrom(s, rx_buff, 65535, 0, NULL, NULL);

You allocate 1500 bytes, but you tell recvfrom() that it has 65535 bytes to play with. That could be a part of your problem.

If it is the problem, running with valgrind or something similar will tell you about abuse very quickly. If you have double free issues, or other similar memory allocation problems, there's a very good chance that valgrind will help you promptly. Remember to compile with debugging (usually the -g option) for both the object files and the final executable. That way, you'll get file names and line numbers to help you with the debugging.