Resolves: RHEL-160670 - squid: Squid: Denial of Service via heap

Use-After-Free vulnerability in ICP handling (CVE-2026-33526)
Resolves: RHEL-160671 - squid: Squid: Denial of Service via crafted
  ICP traffic (CVE-2026-32748)
This commit is contained in:
Luboš Uhliarik 2026-04-22 15:43:36 +02:00
parent f5e0797142
commit 6b3ab26b73
3 changed files with 202 additions and 1 deletions

View File

@ -0,0 +1,179 @@
commit 19fe29039da63063ad078fbeab59b1043de8cdb6
Author: Tomas Korbar <tkorbar@redhat.com>
Date: Fri Mar 27 11:42:00 2026 +0100
Fix CVE-2026-32748
diff --git a/src/ICP.h b/src/ICP.h
index cb13c1c..e7f3a18 100644
--- a/src/ICP.h
+++ b/src/ICP.h
@@ -90,10 +90,7 @@ extern Comm::ConnectionPointer icpOutgoingConn;
extern Ip::Address theIcpPublicHostID;
/// \ingroup ServerProtocolICPAPI
-HttpRequest* icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from);
-
-/// \ingroup ServerProtocolICPAPI
-bool icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request);
+HttpRequestPointer icpGetRequest(const char *url, int reqnum, int fd, const Ip::Address &from);
/// \ingroup ServerProtocolICPAPI
void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from, AccessLogEntryPointer);
@@ -102,7 +99,7 @@ void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pa
icp_opcode icpGetCommonOpcode();
/// \ingroup ServerProtocolICPAPI
-void icpDenyAccess(Ip::Address &from, char *url, int reqnum, int fd);
+void icpDenyAccess(const Ip::Address &from, const char *url, int reqnum, int fd);
/// \ingroup ServerProtocolICPAPI
PF icpHandleUdp;
diff --git a/src/icp_v2.cc b/src/icp_v2.cc
index 1b7a0f3..c6f9a7d 100644
--- a/src/icp_v2.cc
+++ b/src/icp_v2.cc
@@ -425,7 +425,7 @@ icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int
}
void
-icpDenyAccess(Ip::Address &from, char *url, int reqnum, int fd)
+icpDenyAccess(const Ip::Address &from, const char * const url, const int reqnum, const int fd)
{
debugs(12, 2, "icpDenyAccess: Access Denied for " << from << " by " << AclMatchedName << ".");
@@ -440,8 +440,9 @@ icpDenyAccess(Ip::Address &from, char *url, int reqnum, int fd)
}
}
-bool
-icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request)
+/// icpGetRequest() helper that determines whether squid.conf allows the given ICP query
+static bool
+icpAccessAllowed(const Ip::Address &from, HttpRequest * icp_request)
{
/* absent any explicit rules, we deny all */
if (!Config.accessList.icp)
@@ -453,8 +454,8 @@ icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request)
return checklist.fastCheck().allowed();
}
-HttpRequest *
-icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from)
+HttpRequest::Pointer
+icpGetRequest(const char *url, int reqnum, int fd, const Ip::Address &from)
{
if (strpbrk(url, w_space)) {
icpCreateAndSend(ICP_ERR, 0, rfc1738_escape(url), reqnum, 0, fd, from, nullptr);
@@ -462,12 +463,17 @@ icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from)
}
const auto mx = MasterXaction::MakePortless<XactionInitiator::initIcp>();
- auto *result = HttpRequest::FromUrlXXX(url, mx);
- if (!result)
- icpCreateAndSend(ICP_ERR, 0, url, reqnum, 0, fd, from, nullptr);
+ if (const HttpRequest::Pointer request = HttpRequest::FromUrlXXX(url, mx)) {
+ if (!icpAccessAllowed(from, request.getRaw())) {
+ icpDenyAccess(from, url, reqnum, fd);
+ return nullptr;
+ }
- return result;
+ return request;
+ }
+ icpCreateAndSend(ICP_ERR, 0, url, reqnum, 0, fd, from, nullptr);
+ return nullptr;
}
static void
@@ -478,18 +484,11 @@ doV2Query(int fd, Ip::Address &from, char *buf, icp_common_t header)
uint32_t flags = 0;
/* We have a valid packet */
char *url = buf + sizeof(icp_common_t) + sizeof(uint32_t);
- HttpRequest *icp_request = icpGetRequest(url, header.reqnum, fd, from);
+ const auto icp_request = icpGetRequest(url, header.reqnum, fd, from);
if (!icp_request)
return;
- HTTPMSGLOCK(icp_request);
-
- if (!icpAccessAllowed(from, icp_request)) {
- icpDenyAccess(from, url, header.reqnum, fd);
- HTTPMSGUNLOCK(icp_request);
- return;
- }
#if USE_ICMP
if (header.flags & ICP_FLAG_SRC_RTT) {
rtt = netdbHostRtt(icp_request->url.host());
@@ -502,7 +501,7 @@ doV2Query(int fd, Ip::Address &from, char *buf, icp_common_t header)
#endif /* USE_ICMP */
/* The peer is allowed to use this cache */
- ICP2State state(header, icp_request);
+ ICP2State state(header, icp_request.getRaw());
state.fd = fd;
state.from = from;
state.url = xstrdup(url);
@@ -531,8 +530,6 @@ doV2Query(int fd, Ip::Address &from, char *buf, icp_common_t header)
}
icpCreateAndSend(codeToSend, flags, url, header.reqnum, src_rtt, fd, from, state.al);
-
- HTTPMSGUNLOCK(icp_request);
}
void
diff --git a/src/icp_v3.cc b/src/icp_v3.cc
index 290fdae..9cceb9a 100644
--- a/src/icp_v3.cc
+++ b/src/icp_v3.cc
@@ -36,19 +36,13 @@ doV3Query(int fd, Ip::Address &from, char *buf, icp_common_t header)
{
/* We have a valid packet */
char *url = buf + sizeof(icp_common_t) + sizeof(uint32_t);
- HttpRequest *icp_request = icpGetRequest(url, header.reqnum, fd, from);
+ const auto icp_request = icpGetRequest(url, header.reqnum, fd, from);
if (!icp_request)
return;
- if (!icpAccessAllowed(from, icp_request)) {
- icpDenyAccess (from, url, header.reqnum, fd);
- delete icp_request;
- return;
- }
-
/* The peer is allowed to use this cache */
- ICP3State state(header, icp_request);
+ ICP3State state(header, icp_request.getRaw());
state.fd = fd;
state.from = from;
state.url = xstrdup(url);
diff --git a/src/tests/stub_icp.cc b/src/tests/stub_icp.cc
index 95c523b..e4f0b7d 100644
--- a/src/tests/stub_icp.cc
+++ b/src/tests/stub_icp.cc
@@ -9,6 +9,7 @@
#include "squid.h"
#include "AccessLogEntry.h"
#include "comm/Connection.h"
+#include "HttpRequest.h"
#include "ICP.h"
#define STUB_API "icp_*.cc"
@@ -29,11 +30,10 @@ Comm::ConnectionPointer icpIncomingConn;
Comm::ConnectionPointer icpOutgoingConn;
Ip::Address theIcpPublicHostID;
-HttpRequest* icpGetRequest(char *, int, int, Ip::Address &) STUB_RETVAL(nullptr)
-bool icpAccessAllowed(Ip::Address &, HttpRequest *) STUB_RETVAL(false)
+HttpRequest::Pointer icpGetRequest(const char *, int, int, const Ip::Address &) STUB_RETVAL(nullptr)
void icpCreateAndSend(icp_opcode, int, char const *, int, int, int, const Ip::Address &, AccessLogEntryPointer) STUB
icp_opcode icpGetCommonOpcode() STUB_RETVAL(ICP_INVALID)
-void icpDenyAccess(Ip::Address &, char *, int, int) STUB
+void icpDenyAccess(const Ip::Address &, const char *, int, int) STUB
void icpHandleIcpV3(int, Ip::Address &, char *, int) STUB
void icpConnectionShutdown(void) STUB
int icpSetCacheKey(const cache_key *) STUB_RETVAL(0)

View File

@ -0,0 +1,12 @@
diff --git a/src/icp_v2.cc b/src/icp_v2.cc
index 2a4ced3bfab..25f7b71d25e 100644
--- a/src/icp_v2.cc
+++ b/src/icp_v2.cc
@@ -461,7 +461,6 @@ HttpRequest *
icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from)
{
if (strpbrk(url, w_space)) {
- url = rfc1738_escape(url);
icpCreateAndSend(ICP_ERR, 0, rfc1738_escape(url), reqnum, 0, fd, from, nullptr);
return nullptr;
}

View File

@ -2,7 +2,7 @@
Name: squid
Version: 6.10
Release: 10%{?dist}
Release: 12%{?dist}
Summary: The Squid proxy caching server
Epoch: 7
# See CREDITS for breakdown of non GPLv2+ code
@ -53,6 +53,10 @@ Patch210: squid-6.10-dont-stuck-respmod.patch
# Security patches
# https://bugzilla.redhat.com/show_bug.cgi?id=2404736
Patch500: squid-6.10-CVE-2025-62168.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2451574
Patch501: squid-6.10-CVE-2026-33526.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2451577
Patch502: squid-6.10-CVE-2026-32748.patch
# cache_swap.sh
Requires: bash gawk
@ -337,6 +341,12 @@ fi
%changelog
* Wed Apr 22 2026 Luboš Uhliarik <luhliari@redhat.com> - 7:6.10-12
- Resolves: RHEL-160670 - squid: Squid: Denial of Service via heap
Use-After-Free vulnerability in ICP handling (CVE-2026-33526)
- Resolves: RHEL-160671 - squid: Squid: Denial of Service via crafted
ICP traffic (CVE-2026-32748)
* Thu Nov 27 2025 Luboš Uhliarik <luhliari@redhat.com> - 7:6.10-10
- Resolves: RHEL-129457 - "ICAP_ERR_OTHER/408" occurs in icap.log when
downloading a file on RHEL9