Fedora Account System
Red Hat Associate
Red Hat Customer
AI_ONLY_REPORT package: gcc-toolset-15-gcc-15.2.1-7.el10 ------ Summary: Confirmed out-of-bounds read/write in libstdc++ parallel `std::search` (`parallel/search.h`): undersized KMP border-table storage allows `_calc_borders()` to write `_advances[__pattern_length]`, and the full-match path then reads the same out-of-bounds slot, causing a process crash or other in-process memory-safety failure when the parallel search implementation is used. Requirements to exploit: A consuming application must be built with libstdc++ parallel mode (`_GLIBCXX_PARALLEL`) and OpenMP, use random-access iterators, and reach the parallel `std::search` implementation. The attacker then needs control over the haystack and pattern so a full match occurs; the out-of-bounds write additionally requires `__pattern_length > 1`, and normal reachability may depend on the parallel-search threshold unless the application forces parallel mode. Component affected: `gcc-toolset-15-gcc-15.2.1-7.el10`, header-implemented libstdc++ parallel search in `libstdc++-v3/include/parallel/search.h`, primarily `_calc_borders()` and `_search_template()`. Version affected: `gcc-toolset-15-gcc-15.2.1-7.el10` when applications are compiled with `_GLIBCXX_PARALLEL` and OpenMP and reach the parallel `std::search` implementation. Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 6.2 (MEDIUM) AV:L - The confirmed issue is in a local library code path reached by a process using the affected headers; the available evidence does not establish a network-reachable attack surface in the package itself. AC:L - Once the parallel search path is in use, a simple full-match input is sufficient to trigger the fault. PR:N - No privileges are required beyond the ability to supply data to the affected code path. UI:N - No separate user interaction is required after the vulnerable function is invoked. S:U - The impact remains within the calling process. C:N - No confidentiality impact has been demonstrated. I:N - No integrity impact has been demonstrated. A:H - The demonstrated outcome is an out-of-bounds access that can terminate the process. Impact: Moderate. Red Hat rates issues as Moderate when they can affect confidentiality, integrity, or availability under certain circumstances or when a more serious bug class depends on an unlikely configuration. This issue is a confirmed memory-safety flaw with reproducible process-crash impact, but it depends on the non-default libstdc++ parallel-mode extension being enabled in consuming code and the current evidence supports process-level availability impact rather than privilege escalation or code execution. Embargo: no Reason: The issue is not default-reachable, the currently demonstrated impact is process crash/DoS, and affected consumers can mitigate by avoiding the parallel-mode path until a fix is available. Acknowledgement: Aisle Research Vulnerability Details: The parallel Knuth-Morris-Pratt search implementation allocates the border table with `__pattern_length` elements, but `_calc_borders()` writes through index `_length`. Later, when a full match is found, the post-match jump logic reads `__advances[__pattern_length]`. This creates a confirmed out-of-bounds write/read pair on the same array. The previously suspected `__splitters` / `omp_get_num_threads()` path was reviewed separately, but the available code shows allocation occurs after the actual team size is known in the `single` region, so this report is limited to the confirmed `__advances` off-by-one. ```cpp template<typename _RAIter, typename _DifferenceTp> void __calc_borders(_RAIter __elements, _DifferenceTp __length, _DifferenceTp* __off) { ... for (_DifferenceType __j = 2; __j <= __length; __j++) { ... _off[__j] = ++_k; } } ... _DifferenceType __advances[__pattern_length]; _calc_borders(_begin2, __pattern_length, __advances); ... if (__pos_in_pattern == __pattern_length) { ... __found_pattern = true; break; } ... _start += (_pos_in_pattern - __advances[__pos_in_pattern]); _pos_in_pattern = (_advances[__pos_in_pattern] < 0 ? 0 : __advances[__pos_in_pattern]); ``` For `__pattern_length > 1`, the border-table construction writes one element past the end of the stack array. Independently, after a full match, the jump logic reads `__advances[__pattern_length]`. In testing, this is reproducible as a sanitizer-detected out-of-bounds access and can crash the process. Steps to reproduce: 1. Use the following PoC, which forces the parallel strategy and creates a full match: ```cpp #include <parallel/algorithm> #include <parallel/settings.h> #include <vector> #include <iostream> int main() { __gnu_parallel::_Settings s = __gnu_parallel::_Settings::get(); s.algorithm_strategy = __gnu_parallel::force_parallel; __gnu_parallel::_Settings::set(s); std::vector<int> hay(5000, 1); // >= search_minimal_n default std::vector<int> pat{1,1,1,1,1,1,1,1}; // len >= 2, full matches auto it = __gnu_parallel::search(hay.begin(), hay.end(), pat.begin(), pat.end()); std::cout << (it - hay.begin()) << "\n"; } ``` 2. Build with GNU parallel mode, OpenMP, and AddressSanitizer: `g++ -O1 -g -fsanitize=address -fopenmp -D_GLIBCXX_PARALLEL poc.cc -o poc` 3. Run with multiple threads: `OMP_NUM_THREADS=4 ./poc` 4. Observe an AddressSanitizer out-of-bounds report originating in or near `parallel/search.h`, specifically `__calc_borders()` and/or the post-match jump logic. Mitigation: Until a fixed package is available, avoid compiling untrusted-data paths with libstdc++ parallel mode (`_GLIBCXX_PARALLEL`) or avoid forcing the parallel `std::search` implementation in affected consumers. Because this logic is header-implemented, rebuilding affected applications without the parallel-mode extension removes the vulnerable code path. Proposed Fix: ```diff diff --git a/libstdc++-v3/include/parallel/search.h b/libstdc++-v3/include/parallel/search.h @@ _DifferenceType __advances[__pattern_length]; + _DifferenceType __advances[__pattern_length + 1]; _calc_borders(_begin2, __pattern_length, __advances); ``` This aligns the allocation with the algorithm's actual indexing range, which includes `0..__pattern_length`. ------ This report was generated using AI technology. Always review AI-generated content prior to use