[PATCH v3 2/7] pcapng: use malloc instead of fixed buffer size

Stephen Hemminger
2026-01-12T04:54:19Z

The administrative APIs accept comments and other meta data
as strings. This leads to possibility of very large strings
which can overrun the use of fixed size buffers.

Instead, use malloc to allocate a buffer of the necessary
size and handle potential allocation failures.

Bugzilla ID: 1820
Fixes: 8d23ce8f5ee9 ("pcapng: add new library for writing pcapng files")
Cc: stable@dpdk.org

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
lib/pcapng/rte_pcapng.c | 36 ++++++++++++++++++++++++------------
1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/lib/pcapng/rte_pcapng.c b/lib/pcapng/rte_pcapng.c
index 863706a365..c2635d8b03 100644
--- a/lib/pcapng/rte_pcapng.c
+++ b/lib/pcapng/rte_pcapng.c
@@ -37,9 +37,6 @@
/* upper bound for strings in pcapng option data */
#define PCAPNG_STR_MAX UINT16_MAX

-/* upper bound for section, stats and interface blocks (in uint32_t) */
-#define PCAPNG_BLKSIZ (2048 / sizeof(uint32_t))
-
/* Format of the capture file handle */
struct rte_pcapng {
int outfd; /* output file */
@@ -148,7 +145,7 @@ pcapng_section_block(rte_pcapng_t *self,
{
struct pcapng_section_header *hdr;
struct pcapng_option *opt;
- uint32_t buf[PCAPNG_BLKSIZ];
+ uint32_t *buf;
uint32_t len;

len = sizeof(*hdr);
@@ -165,8 +162,11 @@ pcapng_section_block(rte_pcapng_t *self,
len += pcapng_optlen(0);
len += sizeof(uint32_t);

- if (len > sizeof(buf))
+ buf = malloc(len);
+ if (buf == NULL) {
+ errno = ENOMEM;
return -1;
+ }

hdr = (struct pcapng_section_header *)buf;
*hdr = (struct pcapng_section_header) {
@@ -199,7 +199,9 @@ pcapng_section_block(rte_pcapng_t *self,
/* clone block_length after option */
memcpy(opt, &hdr->block_length, sizeof(uint32_t));

- return write(self->outfd, buf, len);
+ ssize_t ret = write(self->outfd, buf, len);
+ free(buf);
+ return ret;
}

/* Write an interface block for a DPDK port */
@@ -217,7 +219,7 @@ rte_pcapng_add_interface(rte_pcapng_t *self, uint16_t port, uint16_t link_type,
struct pcapng_option *opt;
const uint8_t tsresol = 9; /* nanosecond resolution */
uint32_t len;
- uint32_t buf[PCAPNG_BLKSIZ];
+ uint32_t *buf;
char ifname_buf[IF_NAMESIZE];
char ifhw[256];
uint64_t speed = 0;
@@ -279,8 +281,11 @@ rte_pcapng_add_interface(rte_pcapng_t *self, uint16_t port, uint16_t link_type,
len += pcapng_optlen(0);
len += sizeof(uint32_t);

- if (len > sizeof(buf))
+ buf = malloc(len);
+ if (buf == NULL) {
+ errno = ENOMEM;
return -1;
+ }

hdr = (struct pcapng_interface_block *)buf;
*hdr = (struct pcapng_interface_block) {
@@ -327,7 +332,9 @@ rte_pcapng_add_interface(rte_pcapng_t *self, uint16_t port, uint16_t link_type,
/* remember the file index */
self->port_index[port] = self->ports++;

- return write(self->outfd, buf, len);
+ ret = write(self->outfd, buf, len);
+ free(buf);
+ return ret;
}

/*
@@ -344,7 +351,7 @@ rte_pcapng_write_stats(rte_pcapng_t *self, uint16_t port_id,
uint64_t start_time = self->offset_ns;
uint64_t sample_time;
uint32_t optlen, len;
- uint32_t buf[PCAPNG_BLKSIZ];
+ uint32_t *buf;

RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);

@@ -367,8 +374,11 @@ rte_pcapng_write_stats(rte_pcapng_t *self, uint16_t port_id,
optlen += pcapng_optlen(0);

len = sizeof(*hdr) + optlen + sizeof(uint32_t);
- if (len > sizeof(buf))
+ buf = malloc(len);
+ if (buf == NULL) {
+ errno = ENOMEM;
return -1;
+ }

hdr = (struct pcapng_statistics *)buf;
opt = (struct pcapng_option *)(hdr + 1);
@@ -399,7 +409,9 @@ rte_pcapng_write_stats(rte_pcapng_t *self, uint16_t port_id,
/* clone block_length after option */
memcpy(opt, &len, sizeof(uint32_t));

- return write(self->outfd, buf, len);
+ ssize_t ret = write(self->outfd, buf, len);
+ free(buf);
+ return ret;
}

RTE_EXPORT_SYMBOL(rte_pcapng_mbuf_size)
--
2.51.0