Hello, On Wed, Mar 01, 2017 at 05:50:57AM +0100, Joerg Mayer wrote: > I'm trying to get libpcap working on macOS. ... > Trying to understand the problem it looks like accessing struct pcap_md (the > rpcap specific stuff) is broken on non-win32 platforms (or at least on bpf > platforms). > > The intended memory layout seems to be: > > struct pcap_t (containing a pointer to priv if it exits) > priv: > struct pcap_<platform> > struct pcap_md (if compiling with HAVE_REMOTE) > > The current implementation seems to > > a) only allocate the memory for pcap_md on win (pcap_create_interface() in > pcap-win32.c), thus causing an out of bounds access on other platforms. > b) the access to pcap_md is calculated as priv + sizeof(struct pcap_win) > on all platforms which gets redeclared in pcap-new.c and pcap-rpcap.c > for just this purpose. This looks wrong to me but I'm not sure.
OK, I think I managed to fix this one. Please see attached patch. Now it fails (i.e. it no longer crashes!) with: jmayer@newegg:~/worktmp/libpcap/build(master)$ dumpcap -i rpcap://10.122.4.11/wifi0 Capturing on 'rpcap://10.122.4.11/wifi0' dumpcap: Invalid capture filter "(null)" for interface 'rpcap://10.122.4.11/wifi0'. That string isn't a valid capture filter (not-yet-activated pcap_t passed to pcap_compile). See the User's Guide for a description of the capture filter syntax. jmayer@newegg:~/worktmp/libpcap/build(master)$ dumpcap -i rpcap://10.122.4.11/wifi0 -L Data link types of interface rpcap://10.122.4.11/wifi0 (use option -y to set): DLT -3 (not supported) Both of which seem to be libpcap problems (or symptoms of the same problem). Kind regards JÖrg -- Joerg Mayer <jma...@loplof.de> We are stuck with technology when what we really want is just stuff that works. Some say that should read Microsoft instead of technology.
Fix access to struct pcap_md on non-Windows Previously it was assumed that pcap_md was at offset pcap_t + pcap_win. That assumption was only correct on Windows systems. Signed-off-by: Joerg Mayer <jma...@loplof.de> --- pcap-int.h | 3 +++ pcap-new.c | 4 ++-- pcap-rpcap.c | 20 +++++++++----------- pcap.c | 18 +++++++++++++++--- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/pcap-int.h b/pcap-int.h index 5c8c129..e74eec8 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -178,6 +178,9 @@ struct pcap { int break_loop; /* flag set to force break from packet-reading loop */ void *priv; /* private data for methods */ +#ifdef HAVE_REMOTE + void *priv_md; /* private data for rpcap */ +#endif int swapped; FILE *rfile; /* null if live capture, non-null if savefile */ diff --git a/pcap-new.c b/pcap-new.c index 494e425..816f51d 100644 --- a/pcap-new.c +++ b/pcap-new.c @@ -940,7 +940,7 @@ pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, } struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win)); + md = (struct pcap_md *)fp->priv_md; fp->snapshot = snaplen; fp->opt.timeout = read_timeout; @@ -994,7 +994,7 @@ struct pcap_samp *pcap_setsampling(pcap_t *p) { struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win)); + md = (struct pcap_md *)p->priv_md; return &(md->rmt_samp); } diff --git a/pcap-rpcap.c b/pcap-rpcap.c index f5f3fa5..51c07ae 100644 --- a/pcap-rpcap.c +++ b/pcap-rpcap.c @@ -216,7 +216,7 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr **pkt_header, u_c struct timeval tv; /* maximum time the select() can block waiting for data */ struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win)); + md = (struct pcap_md *)p->priv_md; /* * Define the packet buffer timeout, to be used in the select() @@ -423,7 +423,7 @@ static void pcap_cleanup_remote(pcap_t *fp) int active = 0; /* active mode or not? */ struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win)); + md = (struct pcap_md *)fp->priv_md; /* detect if we're in active mode */ temp = activeHosts; @@ -559,7 +559,7 @@ static struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int int retval; /* temp variable which stores functions return value */ struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win)); + md = (struct pcap_md *)p->priv_md; /* * If the capture has still to start, we cannot ask statistics to the other peer, @@ -710,8 +710,7 @@ int pcap_opensource_remote(pcap_t *fp, struct pcap_rmtauth *auth) struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win)); - + md = (struct pcap_md *)fp->priv_md; /* * determine the type of the source (NULL, file, local, remote) @@ -926,7 +925,7 @@ int pcap_startcapture_remote(pcap_t *fp) struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win)); + md = (struct pcap_md *)fp->priv_md; /* * Let's check if sampling has been required. @@ -1386,8 +1385,7 @@ static int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog) struct rpcap_header header; /* To keep the reply message */ struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win)); - + md = (struct pcap_md *)fp->priv_md; if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE)) @@ -1449,7 +1447,7 @@ static int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog) { struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win)); + md = (struct pcap_md *)fp->priv_md; if (!md->rmt_capstarted) { @@ -1482,7 +1480,7 @@ static int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog) int RetVal = 0; struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)fp->priv + sizeof(struct pcap_win)); + md = (struct pcap_md *)fp->priv_md; /* We do not want to capture our RPCAP traffic. So, let's update the filter */ if (md->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP) @@ -1600,7 +1598,7 @@ static int pcap_setsampling_remote(pcap_t *p) struct rpcap_sampling *sampling_pars; /* Structure that is needed to send sampling parameters to the remote host */ struct pcap_md *md; /* structure used when doing a remote live capture */ - md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win)); + md = (struct pcap_md *)p->priv_md; /* If no samping is requested, return 'ok' */ if (md->rmt_samp.method == PCAP_SAMP_NOSAMP) diff --git a/pcap.c b/pcap.c index 3cf4afa..c3e0714 100644 --- a/pcap.c +++ b/pcap.c @@ -124,6 +124,10 @@ struct rtentry; /* declarations in <net/if.h> */ #include "pcap-dbus.h" #endif +#ifdef HAVE_REMOTE +#include "pcap-rpcap.h" +#endif + static int pcap_not_initialized(pcap_t *pcap) { @@ -1257,6 +1261,12 @@ pcap_alloc_pcap_t(char *ebuf, size_t size) { char *chunk; pcap_t *p; + size_t malloc_size; + + malloc_size = sizeof(pcap_t) + size; +#ifdef HAVE_REMOTE + malloc_size += sizeof(struct pcap_md); +#endif /* * Allocate a chunk of memory big enough for a pcap_t @@ -1264,13 +1274,13 @@ pcap_alloc_pcap_t(char *ebuf, size_t size) * structure following it is a private data structure * for the routines that handle this pcap_t. */ - chunk = malloc(sizeof (pcap_t) + size); + chunk = malloc(malloc_size); if (chunk == NULL) { pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } - memset(chunk, 0, sizeof (pcap_t) + size); + memset(chunk, 0, malloc_size); /* * Get a pointer to the pcap_t at the beginning. @@ -1292,7 +1302,9 @@ pcap_alloc_pcap_t(char *ebuf, size_t size) */ p->priv = (void *)(chunk + sizeof (pcap_t)); } - +#ifdef HAVE_REMOTE + p->priv_md = (void *)(chunk + sizeof(pcap_t) + size); +#endif return (p); } -- 2.10.1 (Apple Git-78)
_______________________________________________ tcpdump-workers mailing list tcpdump-workers@lists.tcpdump.org https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers