mirror of
https://git.yoctoproject.org/poky
synced 2026-10-23 07:28:17 +00:00
libpcap: Fix CVE-2026-18238
NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-18238 Upstream-commit: https://github.com/the-tcpdump-group/libpcap/commit/b9590d482986d64673712460aae1d48d11fa0473 (From OE-Core rev: 940dee79d02890b06b91bb394ba51b933e3a1dbb) Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech> Signed-off-by: Yoann Congal <yoann.congal@smile.fr> Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
1 parent
358a044360
commit
63f658cb2b
2 files changed
+223
No files matched your search
@@ -0,0 +1,222 @@
|
||||
From b9590d482986d64673712460aae1d48d11fa0473 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)
|
||||
|
||||
Notes on backporting to 1.10.4:
|
||||
- The upstream CHANGES/changelog hunk is not backported.
|
||||
|
||||
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>
|
||||
---
|
||||
diff --git a/pcap-rpcap.c b/pcap-rpcap.c
|
||||
index 22fc7363..30fbd6d6 100644
|
||||
--- a/pcap-rpcap.c
|
||||
+++ b/pcap-rpcap.c
|
||||
@@ -388,10 +388,9 @@ rpcap_deseraddr(struct rpcap_sockaddr *sockaddrin, struct sockaddr_storage **soc
|
||||
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;
|
||||
|
||||
@@ -448,13 +447,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 */
|
||||
@@ -470,6 +491,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))
|
||||
{
|
||||
/*
|
||||
@@ -479,8 +502,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
|
||||
@@ -495,6 +528,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))
|
||||
{
|
||||
/*
|
||||
@@ -514,27 +548,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. */
|
||||
@@ -557,27 +599,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.");
|
||||
@@ -23,6 +23,7 @@ SRC_URI = "https://www.tcpdump.org/release/${BP}.tar.gz \
|
||||
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] = "ed19a0383fad72e3ad435fd239d7cd80d64916b87269550159d20e47160ebe5f"
|
||||
|
||||
Reference in new issue
Block a user