Skip to content

Commit c60ebf1

Browse files
committed
Make sure no read routine process more than INT_MAX packets.
Some read routines don't read a single bufferful of packets and process just those packets; if packets continue to be made available, they could conceivably process an arbitrary number of packets. That would mean that the packet count overflows; either that makes it look like a negative number, making it look as if an error occurred, or makes it look like a too-small positive number. This can't be fixed by making the count 64-bit, as it ultimately gets returned by pcap_dispatch(), which is defined to return an int. Instead, if the maximum packet count argument to those routines is a value that means "no maximum", we set the maximum to INT_MAX. Those routines are *not* defined to loop forever, so this isn't an issue. This should fix issue #1087.
1 parent f570e6b commit c60ebf1

16 files changed

+191
-19
lines changed

dlpisubs.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,12 @@ pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
146146
#endif
147147
#endif
148148

149-
/* Loop through packets */
149+
/*
150+
* Loop through packets.
151+
*
152+
* This assumes that a single buffer of packets will have
153+
* <= INT_MAX packets, so the packet count doesn't overflow.
154+
*/
150155
ep = bufp + len;
151156
n = 0;
152157

pcap-airpcap.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,9 @@ airpcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
627627

628628
/*
629629
* Loop through each packet.
630+
*
631+
* This assumes that a single buffer of packets will have
632+
* <= INT_MAX packets, so the packet count doesn't overflow.
630633
*/
631634
#define bhp ((AirpcapBpfHeader *)bp)
632635
n = 0;

pcap-bpf.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,9 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
11771177

11781178
/*
11791179
* Loop through each packet.
1180+
*
1181+
* This assumes that a single buffer of packets will have
1182+
* <= INT_MAX packets, so the packet count doesn't overflow.
11801183
*/
11811184
#ifdef BIOCSTSTAMP
11821185
#define bhp ((struct bpf_xhdr *)bp)

pcap-dag.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,12 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
391391

392392
}
393393

394-
/* Process the packets. */
394+
/*
395+
* Process the packets.
396+
*
397+
* This assumes that a single buffer of packets will have
398+
* <= INT_MAX packets, so the packet count doesn't overflow.
399+
*/
395400
while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) {
396401

397402
unsigned short packet_len = 0;

pcap-dos.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <signal.h>
1313
#include <float.h>
1414
#include <fcntl.h>
15+
#include <limits.h> /* for INT_MAX */
1516
#include <io.h>
1617

1718
#if defined(USE_32BIT_DRIVERS)
@@ -355,7 +356,22 @@ pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
355356
{
356357
int rc, num = 0;
357358

358-
while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
359+
/*
360+
* This can conceivably process more than INT_MAX packets,
361+
* which would overflow the packet count, causing it either
362+
* to look like a negative number, and thus cause us to
363+
* return a value that looks like an error, or overflow
364+
* back into positive territory, and thus cause us to
365+
* return a too-low count.
366+
*
367+
* Therefore, if the packet count is unlimited, we clip
368+
* it at INT_MAX; this routine is not expected to
369+
* process packets indefinitely, so that's not an issue.
370+
*/
371+
if (PACKET_COUNT_IS_UNLIMITED(cnt))
372+
cnt = INT_MAX;
373+
374+
while (num <= cnt)
359375
{
360376
if (p->fd <= 0)
361377
return (-1);

pcap-dpdk.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ env DPDK_CFG="--log-level=debug -l0 -dlibrte_pmd_e1000.so -dlibrte_pmd_ixgbe.so
8585
#include <stdlib.h>
8686
#include <string.h>
8787
#include <unistd.h>
88+
#include <limits.h> /* for INT_MAX */
8889
#include <time.h>
8990

9091
#include <sys/time.h>
@@ -331,13 +332,28 @@ static int pcap_dpdk_dispatch(pcap_t *p, int max_cnt, pcap_handler cb, u_char *c
331332
u_char *large_buffer=NULL;
332333
int timeout_ms = p->opt.timeout;
333334

334-
if ( !PACKET_COUNT_IS_UNLIMITED(max_cnt) && max_cnt < MAX_PKT_BURST){
335+
/*
336+
* This can conceivably process more than INT_MAX packets,
337+
* which would overflow the packet count, causing it either
338+
* to look like a negative number, and thus cause us to
339+
* return a value that looks like an error, or overflow
340+
* back into positive territory, and thus cause us to
341+
* return a too-low count.
342+
*
343+
* Therefore, if the packet count is unlimited, we clip
344+
* it at INT_MAX; this routine is not expected to
345+
* process packets indefinitely, so that's not an issue.
346+
*/
347+
if (PACKET_COUNT_IS_UNLIMITED(max_cnt))
348+
max_cnt = INT_MAX;
349+
350+
if (max_cnt < MAX_PKT_BURST){
335351
burst_cnt = max_cnt;
336352
}else{
337353
burst_cnt = MAX_PKT_BURST;
338354
}
339355

340-
while( PACKET_COUNT_IS_UNLIMITED(max_cnt) || pkt_cnt < max_cnt){
356+
while( pkt_cnt < max_cnt){
341357
if (p->break_loop){
342358
p->break_loop = 0;
343359
return PCAP_ERROR_BREAK;

pcap-linux.c

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4064,9 +4064,22 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
40644064
}
40654065
}
40664066

4067-
/* non-positive values of max_packets are used to require all
4068-
* packets currently available in the ring */
4069-
while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
4067+
/*
4068+
* This can conceivably process more than INT_MAX packets,
4069+
* which would overflow the packet count, causing it either
4070+
* to look like a negative number, and thus cause us to
4071+
* return a value that looks like an error, or overflow
4072+
* back into positive territory, and thus cause us to
4073+
* return a too-low count.
4074+
*
4075+
* Therefore, if the packet count is unlimited, we clip
4076+
* it at INT_MAX; this routine is not expected to
4077+
* process packets indefinitely, so that's not an issue.
4078+
*/
4079+
if (PACKET_COUNT_IS_UNLIMITED(max_packets))
4080+
max_packets = INT_MAX;
4081+
4082+
while (pkts < max_packets) {
40704083
/*
40714084
* Get the current ring buffer frame, and break if
40724085
* it's still owned by the kernel.
@@ -4159,9 +4172,22 @@ pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback,
41594172
return pkts;
41604173
}
41614174

4162-
/* non-positive values of max_packets are used to require all
4163-
* packets currently available in the ring */
4164-
while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
4175+
/*
4176+
* This can conceivably process more than INT_MAX packets,
4177+
* which would overflow the packet count, causing it either
4178+
* to look like a negative number, and thus cause us to
4179+
* return a value that looks like an error, or overflow
4180+
* back into positive territory, and thus cause us to
4181+
* return a too-low count.
4182+
*
4183+
* Therefore, if the packet count is unlimited, we clip
4184+
* it at INT_MAX; this routine is not expected to
4185+
* process packets indefinitely, so that's not an issue.
4186+
*/
4187+
if (PACKET_COUNT_IS_UNLIMITED(max_packets))
4188+
max_packets = INT_MAX;
4189+
4190+
while (pkts < max_packets) {
41654191
int packets_to_read;
41664192

41674193
if (handlep->current_packet == NULL) {
@@ -4174,12 +4200,12 @@ pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback,
41744200
}
41754201
packets_to_read = handlep->packets_left;
41764202

4177-
if (!PACKET_COUNT_IS_UNLIMITED(max_packets) &&
4178-
packets_to_read > (max_packets - pkts)) {
4203+
if (packets_to_read > (max_packets - pkts)) {
41794204
/*
4180-
* We've been given a maximum number of packets
4181-
* to process, and there are more packets in
4182-
* this buffer than that. Only process enough
4205+
* There are more packets in the buffer than
4206+
* the number of packets we have left to
4207+
* process to get up to the maximum number
4208+
* of packets to process. Only process enough
41834209
* of them to get us up to that maximum.
41844210
*/
41854211
packets_to_read = max_packets - pkts;

pcap-netfilter-linux.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c
136136
bp = (unsigned char *)handle->buffer;
137137
} else
138138
bp = handle->bp;
139+
140+
/*
141+
* Loop through each message.
142+
*
143+
* This assumes that a single buffer of message will have
144+
* <= INT_MAX packets, so the message count doesn't overflow.
145+
*/
139146
ep = bp + len;
140147
while (bp < ep) {
141148
const struct nlmsghdr *nlh = (const struct nlmsghdr *) bp;

pcap-nit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
125125
* Loop through each packet. The increment expression
126126
* rounds up to the next int boundary past the end of
127127
* the previous packet.
128+
*
129+
* This assumes that a single buffer of packets will have
130+
* <= INT_MAX packets, so the packet count doesn't overflow.
128131
*/
129132
n = 0;
130133
ep = bp + cc;

pcap-npf.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#endif
3737

3838
#include <errno.h>
39+
#include <limits.h> /* for INT_MAX */
3940
#define PCAP_DONT_INCLUDE_PCAP_BPF_H
4041
#include <Packet32.h>
4142
#include <pcap-int.h>
@@ -633,6 +634,9 @@ pcap_read_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
633634

634635
/*
635636
* Loop through each packet.
637+
*
638+
* This assumes that a single buffer of packets will have
639+
* <= INT_MAX packets, so the packet count doesn't overflow.
636640
*/
637641
#define bhp ((struct bpf_hdr *)bp)
638642
n = 0;
@@ -792,6 +796,21 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
792796

793797
endofbuf = (char*)header + cc;
794798

799+
/*
800+
* This can conceivably process more than INT_MAX packets,
801+
* which would overflow the packet count, causing it either
802+
* to look like a negative number, and thus cause us to
803+
* return a value that looks like an error, or overflow
804+
* back into positive territory, and thus cause us to
805+
* return a too-low count.
806+
*
807+
* Therefore, if the packet count is unlimited, we clip
808+
* it at INT_MAX; this routine is not expected to
809+
* process packets indefinitely, so that's not an issue.
810+
*/
811+
if (PACKET_COUNT_IS_UNLIMITED(cnt))
812+
cnt = INT_MAX;
813+
795814
/*
796815
* Cycle through the packets
797816
*/

0 commit comments

Comments
 (0)