From 8276e4ff5f5219ccc377151d4f770ca55ea1ce30 Mon Sep 17 00:00:00 2001 From: pkgagent Date: Wed, 29 Jul 2026 17:23:50 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20unbounded=20chunk=20size=20allocation=20i?= =?UTF-8?q?n=20pcm-sensor-server=20readChunkedData=20leading=20to=20denial?= =?UTF-8?q?=20of=20servi=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...nk-sizes-in-pcm-sensor-serve-3b19d51.patch | 73 +++++++++++++++++++ pcm.spec | 7 +- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 pcm-202405-validate-chunk-sizes-in-pcm-sensor-serve-3b19d51.patch diff --git a/pcm-202405-validate-chunk-sizes-in-pcm-sensor-serve-3b19d51.patch b/pcm-202405-validate-chunk-sizes-in-pcm-sensor-serve-3b19d51.patch new file mode 100644 index 0000000..e96915b --- /dev/null +++ b/pcm-202405-validate-chunk-sizes-in-pcm-sensor-serve-3b19d51.patch @@ -0,0 +1,73 @@ +From 3b19d51957a6cf000a4cd9c28f08acd5964a1408 Mon Sep 17 00:00:00 2001 +From: Copilot <198982749+Copilot@users.noreply.github.com> +Date: Tue, 14 Jul 2026 08:21:16 +0200 +Subject: [PATCH] Validate chunk sizes in pcm-sensor-server readChunkedData to + prevent unbounded allocation (#947) + +* Validate chunk size in readChunkedData to prevent unbounded allocation + +* Validate chunk header parsing + +--------- + +Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> +--- + src/pcm-sensor-server.cpp | 39 ++++++++++++++++++++++++++++++++------- + 1 file changed, 32 insertions(+), 7 deletions(-) +diff --git a/src/pcm-sensor-server.cpp b/src/pcm-sensor-server.cpp +index 72a89ec..1238a14 100644 +--- a/src/pcm-sensor-server.cpp ++++ b/src/pcm-sensor-server.cpp +@@ -2156,6 +2156,10 @@ public: + } + + protected: ++ // Upper bound on a single chunk's declared size to prevent attacker ++ // controlled chunk headers from forcing unbounded allocations. ++ static constexpr unsigned long long MAX_CHUNK_BYTES = 64ULL * 1024ULL * 1024ULL; ++ + std::string readData( socketstream& in, size_t length ) { + std::string data( length, '\0' ); + in.read( &data[0], length ); +@@ -2165,13 +2169,34 @@ protected: + std::string readChunkedData( socketstream& in ) { + std::string chunkHeader; + std::string data; +- std::getline( in, chunkHeader, '\n' ); +- // Final header starts with 0, rest of the line is not important +- while ( '0' != chunkHeader[0] ) { +- // chunkheader: hexadecimal numbers followed by an optional semi-colon with a comment and a \r +- // stoll should filter all that crap out for us and return just the hexadecimal digits +- DBG( 3, "chunkHeader (ater check for 0): '", chunkHeader, "'" ); +- size_t length = std::stoll( chunkHeader, nullptr, 16 ); ++ while ( true ) { ++ std::getline( in, chunkHeader, '\n' ); ++ DBG( 3, "chunkHeader (after check for 0): '", chunkHeader, "'" ); ++ // chunkHeader: hexadecimal numbers followed by an optional semi-colon ++ // with a chunk extension and a trailing \r ++ const auto chunkSizeEnd = chunkHeader.find_first_not_of( "0123456789abcdefABCDEF" ); ++ if ( chunkHeader.empty() || chunkSizeEnd == 0 || chunkSizeEnd == std::string::npos ) ++ throw std::runtime_error( "Invalid chunk size line in chunked request body" ); ++ const std::string chunkSuffix = chunkHeader.substr( chunkSizeEnd ); ++ if ( ( chunkSuffix[0] == ';' && chunkSuffix.back() != '\r' ) || ++ ( chunkSuffix[0] != ';' && chunkSuffix != "\r" ) ) { ++ throw std::runtime_error( "Invalid chunk size line in chunked request body" ); ++ } ++ // Validate the parsed chunk length before using it as an allocation ++ // size. An unbounded positive value could be used to force a large ++ // allocation (memory-growth denial of service) via ++ // Transfer-Encoding: chunked. ++ unsigned long long parsedLength = 0; ++ try { ++ parsedLength = std::stoull( chunkHeader.substr( 0, chunkSizeEnd ), nullptr, 16 ); ++ } catch ( std::exception const & e ) { ++ throw std::runtime_error( std::string( "Invalid chunk size in chunked request body: " ) + e.what() ); ++ } ++ if ( parsedLength > MAX_CHUNK_BYTES ) ++ throw std::runtime_error( "Chunk size in chunked request body exceeds the maximum allowed size" ); ++ size_t length = static_cast( parsedLength ); ++ if ( length == 0 ) ++ break; + DBG( 3, "length: '", length, "'" ); + // Initialize chunk to all zeros + std::string chunk( length, '\0' ); diff --git a/pcm.spec b/pcm.spec index 622dbab..0e44f67 100644 --- a/pcm.spec +++ b/pcm.spec @@ -1,7 +1,7 @@ Summary: Processor Counter Monitor Name: pcm Version: 202405 -Release: 3%{?dist} +Release: 4%{?dist} License: BSD Url: https://github.com/opcm/pcm Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz @@ -10,6 +10,7 @@ Patch3000: keep-GenuineIntel-6-55-7-json.patch # https://github.com/intel/pcm/issues/823 Patch0001: Handle-TPMI-initilization-for-systems-without-access-to-MCFG.patch +Patch0002: pcm-202405-validate-chunk-sizes-in-pcm-sensor-serve-3b19d51.patch BuildRequires: gcc gcc-c++ make cmake ExclusiveArch: x86_64 @@ -41,6 +42,10 @@ rm -rf %{buildroot}/usr/share/doc/PCM/*.txt %{_datadir}/%{name}/ %changelog +* Wed Jul 29 2026 PkgAgent Robot - 202405-4 +- [Type] security +- [DESC] Fix unbounded chunk size allocation in pcm-sensor-server readChunkedData leading to denial of service + * Thu Sep 26 2024 OpenCloudOS Release Engineering - 202405-3 - Rebuilt for clarifying the packages requirement in BaseOS and AppStream -- Gitee