Home > front end >  pcap_next causes a segmentation fault
pcap_next causes a segmentation fault

Time:10-07

I'm writing a simple packet capture program which captures three packets using pcap functions. But it crashes with a segmentation fault. Below is the source code for the program.

#include <pcap.h>
#include <stdlib.h>
#include <stdio.h>
#include "dump.h"

void pcap_fatal(const char *failed_in, const char *errbuf){
    printf("Fata Error in %s: %s\n", failed_in, errbuf);
    exit(1);
}

int main(){
    struct pcap_pkthdr *header;
    const u_char *packet;
    char errbuf[PCAP_ERRBUF_SIZE];
    char *device;
    pcap_t *pcap_handle;
    int i;

    /*look for a device to capture packets*/
    device = pcap_lookupdev(errbuf);
    if(device == NULL)
        pcap_fatal("pcap_lookupdev", errbuf);
    printf("Sniffing on device %s\n", device);

    /*opens the packet capturing device*/
    pcap_handle = pcap_open_live(device, 4096, 1, 0, errbuf);
    if(pcap_handle < 0){
        perror("ERROR: while opening pcap device");
        exit(1);
    }

    for(i=0;i<3;i  ){
        printf("\n===packet %d===\n", i 1);
        packet = pcap_next(pcap_handle, header);
        printf("Got a %d bute packet\n", header->len);
        dump(packet, header->len);
    }
    
    pcap_close(pcap_handle);
}

Can you figure out what is going on ??

CodePudding user response:

Regarding condition if(pcap_handle < 0): the API documentation here, https://www.tcpdump.org/manpages/pcap.3pcap.html, indicates that function "pcap_open_live() returns a pcap_t * on success and NULL on failure. The error check should probably be if(pcap_handle == NULL) in this case.

In the current program, if pcap_open_live() were to return NULL indicating a failure, then I would expect line packet = pcap_next(pcap_handle, header); to set header to NULL or else leave it in its uninitialized state.

On the following line, header is dereferenced, and if uninitialized or NULL would likely result in a segmentation fault.

So to summarize see the comments added below:

#include <pcap.h>
#include <stdlib.h>
#include <stdio.h>
#include "dump.h"

void pcap_fatal(const char *failed_in, const char *errbuf){
    printf("Fata Error in %s: %s\n", failed_in, errbuf);
    exit(1);
}

int main(){
    struct pcap_pkthdr *header;
    const u_char *packet;
    char errbuf[PCAP_ERRBUF_SIZE];
    char *device;
    pcap_t *pcap_handle;
    int i;

    /*look for a device to capture packets*/
    device = pcap_lookupdev(errbuf);
    if(device == NULL)
        pcap_fatal("pcap_lookupdev", errbuf);
    printf("Sniffing on device %s\n", device);

    /*opens the packet capturing device*/
    pcap_handle = pcap_open_live(device, 4096, 1, 0, errbuf); // << Fails and returns NULL.
    if(pcap_handle < 0){                                      // << Passes since value is NULL (typically zero).
        perror("ERROR: while opening pcap device");
        exit(1);
    }

    for(i=0;i<3;i  ){
        printf("\n===packet %d===\n", i 1);
        packet = pcap_next(pcap_handle, header);              // << Sets header to NULL or leaves uninitialized.
        printf("Got a %d bute packet\n", header->len);        // << Dereferences pointer to nothing causing segmentation fault.
        dump(packet, header->len);
    }
    
    pcap_close(pcap_handle);
}

I would recommend the following replacement code with a few extra checks for added protection:

#include <pcap.h>
#include <stdlib.h>
#include <stdio.h>
#include "dump.h"

void pcap_fatal(const char *failed_in, const char *errbuf){
    printf("Fata Error in %s: %s\n", failed_in, errbuf);
    exit(1);
}

int main(){
    struct pcap_pkthdr *header;
    const u_char *packet;
    char errbuf[PCAP_ERRBUF_SIZE];
    char *device;
    pcap_t *pcap_handle;
    int i;

    /*look for a device to capture packets*/
    device = pcap_lookupdev(errbuf);
    if(device == NULL)
        pcap_fatal("pcap_lookupdev", errbuf);
    printf("Sniffing on device %s\n", device);

    /*opens the packet capturing device*/
    pcap_handle = pcap_open_live(device, 4096, 1, 0, errbuf);
    if(pcap_handle == NULL){
        perror("ERROR: while opening pcap device");
        exit(1);
    }

    for(i=0;i<3;i  ){
        printf("\n===packet %d===\n", i 1);
        packet = pcap_next(pcap_handle, header);
        if((packet != NULL) && (header != NULL)){
            printf("Got a %d bute packet\n", header->len);
            dump(packet, header->len);
        }
    }
    
    pcap_close(pcap_handle);
}
  • Related