new file mode 100644
@@ -0,0 +1,234 @@
+From 5aa9cfee8eb44967dec96199fde879022e4426d4 Mon Sep 17 00:00:00 2001
+From: Denis Ovsienko <denis@ovsienko.info>
+Date: Sat, 8 Aug 2026 00:31:10 +0100
+Subject: [PATCH] CVE-2026-18238: Fix RPCAP_MSG_PACKET validation.
+
+This vulnerability was originally reported publicly, hence no credit is
+given.
+
+When pcap_read_nocb_remote() validates a received message, it does not
+verify that there is a complete RPCAP_MSG_PACKET header in the rpcap
+general payload, also it uses an incorrect value to validate the length
+declared in the RPCAP_MSG_PACKET header. The latter can lead the
+protocol client to over-read the message buffer by 20 bytes, which in at
+least one scenario can cause a SIGSEGV.
+
+Fix this problem, as well as a potential integer overflow in the UDP
+code path on 32-bit architectures. To make message encoding and
+validation easier to follow, re-jig a few variables and update comments.
+
+(backported from commit 2d67e814e8d3791a8b508c359f94688c5669cce9)
+
+(cherry picked from commit b9590d482986d64673712460aae1d48d11fa0473)
+
+Upstream-Status: Backport [https://github.com/the-tcpdump-group/libpcap/commit/b9590d482986d64673712460aae1d48d11fa0473]
+CVE: CVE-2026-18238
+Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
+---
+ CHANGES | 1 +
+ pcap-rpcap.c | 117 ++++++++++++++++++++++++++++++++++++---------------
+ 2 files changed, 85 insertions(+), 33 deletions(-)
+diff --git a/CHANGES b/CHANGES
+index 4f24f94..8e29fd7 100644
+--- a/CHANGES
++++ b/CHANGES
+@@ -6,6 +6,7 @@
+ CVE-2026-6244: Avoid division by zero via pcap_offline_filter().
+ CVE-2026-6554: Limit "ja L" looping in pcap_offline_filter().
+ CVE-2026-18313: Fix a memory leak in rpcapd.
++ CVE-2026-18238: Fix RPCAP_MSG_PACKET validation.
+
+ Tuesday, December 30, 2025 / The Tcpdump Group
+ Summary for 1.10.6 libpcap release
+diff --git a/pcap-rpcap.c b/pcap-rpcap.c
+index 8f8960b9..b7f54641 100644
+--- a/pcap-rpcap.c
++++ b/pcap-rpcap.c
+@@ -389,10 +389,9 @@ rpcap_deseraddr(struct rpcap_sockaddr *sockaddrin, struct sockaddr **sockaddrout
+ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_char **pkt_data)
+ {
+ struct pcap_rpcap *pr = p->priv; /* structure used when doing a remote live capture */
+- struct rpcap_header *header; /* general header according to the RPCAP format */
+- struct rpcap_pkthdr *net_pkt_header; /* header of the packet, from the message */
++ struct rpcap_header *gen_header; /* rpcap general header */
++ struct rpcap_pkthdr *net_pkt_header; /* RPCAP_MSG_PACKET header */
+ u_char *net_pkt_data; /* packet data from the message */
+- uint32 plen;
+ int retval = 0; /* generic return value */
+ int msglen;
+
+@@ -449,13 +448,35 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
+ return 0;
+
+ /*
+- * We have to define 'header' as a pointer to a larger buffer,
+- * because in case of UDP we have to read all the message within a single call
++ * pcap_startcapture_remote() has pointed p->buffer to a buffer large
++ * enough to contain all of the following data at once:
++ *
++ * - a fixed-size rpcap general header
++ * - a fixed-size RPCAP_MSG_PACKET header
++ * - p->snapshot worth of bytes of a captured packet
++ *
++ * This is sufficient for all code paths below.
+ */
+- header = (struct rpcap_header *) p->buffer;
++ gen_header = (struct rpcap_header *)p->buffer;
+ net_pkt_header = (struct rpcap_pkthdr *) ((char *)p->buffer + sizeof(struct rpcap_header));
+ net_pkt_data = (u_char *)p->buffer + sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr);
+
++ /*
++ * Step 1: to receive a message that does not immediately look
++ * malformed, consider it as a fixed-size rpcap general header followed
++ * by a variable-size rpcap general payload and require:
++ *
++ * - a complete rpcap general header to land in the buffer, and
++ * - the header to declare an rpcap general payload length that fits
++ * in the buffer after the header, and
++ * - the complete declared payload to land in the buffer after the
++ * header.
++ *
++ * Since this step loosely corresponds to rpcap_process_msg_header(),
++ * which among other things converts rpcap_header.plen to host byte
++ * order, mimic that as well to produce a valid argument for
++ * rpcap_check_msg_ver() later on.
++ */
+ if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+ {
+ /* Read the entire message from the network */
+@@ -471,6 +492,8 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
+ /* Interrupted receive. */
+ return 0;
+ }
++
++ // Require a complete rpcap general header to be present.
+ if ((size_t)msglen < sizeof(struct rpcap_header))
+ {
+ /*
+@@ -480,8 +503,18 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
+ "UDP packet message is shorter than an rpcap header");
+ return -1;
+ }
+- plen = ntohl(header->plen);
+- if ((size_t)msglen < sizeof(struct rpcap_header) + plen)
++ gen_header->plen = ntohl(gen_header->plen);
++
++ /*
++ * Validate the rpcap general payload length declared in the
++ * rpcap general header. Use subtraction to avoid an integer
++ * overflow:
++ *
++ * 0 <= gen_header->plen <= UINT32_MAX
++ * sizeof(struct rpcap_header) <= msglen <= p->bufsize
++ * p->bufsize is significantly less than UINT32_MAX
++ */
++ if (gen_header->plen > (size_t)msglen - sizeof(struct rpcap_header))
+ {
+ /*
+ * Message is shorter than the header claims it
+@@ -496,6 +529,7 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
+ {
+ int status;
+
++ // Receive a complete rpcap general header from the network.
+ if ((size_t)p->cc < sizeof(struct rpcap_header))
+ {
+ /*
+@@ -515,27 +549,35 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
+ return 0;
+ }
+ }
++ gen_header->plen = ntohl(gen_header->plen);
+
+ /*
+- * We have the header, so we know how long the
+- * message payload is. The size we should get
+- * is the size of the packet header plus the
+- * size of the payload.
++ * Validate the rpcap general payload length declared in the
++ * rpcap general header. Use subtraction to avoid an integer
++ * overflow:
++ *
++ * 0 <= gen_header->plen <= UINT32_MAX
++ * sizeof(struct rpcap_header) < p->bufsize
++ * p->bufsize is significantly less than UINT32_MAX
+ */
+- plen = ntohl(header->plen);
+- if (plen > p->bufsize - sizeof(struct rpcap_header))
++ if (gen_header->plen > p->bufsize - sizeof(struct rpcap_header))
+ {
+ /*
+ * This is bigger than the largest
+- * record we'd expect. (We do it by
+- * subtracting in order to avoid an
+- * overflow.)
++ * record we'd expect.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Server sent us a message larger than the largest expected packet message");
+ return -1;
+ }
+- status = rpcap_read_packet_msg(pr, p, sizeof(struct rpcap_header) + plen);
++
++ /*
++ * Receive the declared rpcap general payload from the network.
++ *
++ * p->cc == sizeof(struct rpcap_header)
++ * p->bp == p->buffer + sizeof(struct rpcap_header)
++ */
++ status = rpcap_read_packet_msg(pr, p, sizeof(struct rpcap_header) + gen_header->plen);
+ if (status == -1)
+ {
+ /* Network error. */
+@@ -558,27 +600,36 @@ static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_ch
+
+ /*
+ * We have the entire message.
+- */
+- header->plen = plen;
+-
+- /*
+- * Did the server specify the version we negotiated?
++ * Step 2: to validate the received message further, require:
++ *
++ * - the rpcap general header to have the correct version and type, and
++ * - the rpcap general payload to be large enough to contain at least a
++ * complete RPCAP_MSG_PACKET header, and
++ * - the RPCAP_MSG_PACKET header to declare an RPCAP_MSG_PACKET payload
++ * (i.e. the captured packet) length that fits in the rpcap general
++ * payload (not the entire buffer) after the RPCAP_MSG_PACKET header.
+ */
+ if (rpcap_check_msg_ver(pr->rmt_sockdata, pr->data_ssl, pr->protocol_version,
+- header, p->errbuf) == -1)
+- {
++ gen_header, p->errbuf) == -1)
++ return 0; /* Return 'no packets received' */
++ if (gen_header->type != RPCAP_MSG_PACKET)
+ return 0; /* Return 'no packets received' */
++ if (gen_header->plen < sizeof(struct rpcap_pkthdr))
++ {
++ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
++ "Received an incomplete RPCAP_MSG_PACKET header.");
++ return -1;
+ }
+-
+ /*
+- * Is this a RPCAP_MSG_PACKET message?
++ * Validate the RPCAP_MSG_PACKET payload length declared in the
++ * RPCAP_MSG_PACKET header. Use subtraction to avoid an integer
++ * overflow:
++ *
++ * 0 <= ntohl(net_pkt_header->caplen) <= UINT32_MAX
++ * sizeof(struct rpcap_pkthdr) <= gen_header->plen
++ * gen_header->plen is significantly less than UINT32_MAX
+ */
+- if (header->type != RPCAP_MSG_PACKET)
+- {
+- return 0; /* Return 'no packets received' */
+- }
+-
+- if (ntohl(net_pkt_header->caplen) > plen)
++ if (ntohl(net_pkt_header->caplen) > gen_header->plen - sizeof(struct rpcap_pkthdr))
+ {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Packet's captured data goes past the end of the received packet message.");
@@ -18,6 +18,7 @@ SRC_URI = "https://www.tcpdump.org/release/${BP}.tar.xz \
file://04-CVE-2026-6244.patch \
file://05-CVE-2026-6554.patch \
file://06-CVE-2026-18313.patch \
+ file://07-CVE-2026-18238.patch \
"
SRC_URI[sha256sum] = "ec97d1206bdd19cb6bdd043eaa9f0037aa732262ec68e070fd7c7b5f834d5dfc"
NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-18238 Upstream-commit: https://github.com/the-tcpdump-group/libpcap/commit/b9590d482986d64673712460aae1d48d11fa0473 Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech> --- .../libpcap/libpcap/07-CVE-2026-18238.patch | 234 ++++++++++++++++++ .../libpcap/libpcap_1.10.6.bb | 1 + 2 files changed, 235 insertions(+) create mode 100644 meta/recipes-connectivity/libpcap/libpcap/07-CVE-2026-18238.patch