GCC's GCOV instrumentation can merge global branch counters with loop
index variables as an optimization. In inflate_fast(), the inner copy
loops (e.g., the pattern fill at line 276-278) get transformed so that
the GCOV counter value is loaded multiple times to compute the loop
base address and bounds.
Since GCOV counters are global (not per-CPU), concurrent execution of
inflate_fast() on different CPUs causes the counter to change between
loads. This results in inconsistent loop bounds and base address
calculations, leading to out-of-bounds memory writes.
The crash manifests during IPComp (IP Payload Compression) processing
when both compress and decompress paths run zlib on different CPUs:
BUG: unable to handle page fault for address: ffffd0a3c0902ffa
RIP: inflate_fast+1431
Call Trace:
zlib_inflate
__deflate_decompress
crypto_comp_decompress
ipcomp_decompress [xfrm_ipcomp]
ipcomp_input [xfrm_ipcomp]
xfrm_input
xfrm4_rcv
At the crash point, the compiler generated:
mov %r9, __gcov0.inflate_fast+216 # load 1: used for start index
mov %r9, __gcov0.inflate_fast+216 # load 2: used for base adjustment
mov %r11, __gcov0.inflate_fast+216 # load 3: used for end bound
lea (%r8,%r9,2), %r8 # adjust base with load 2
...
loop:
mov %bx, (%r8,%r9,2) # CRASH: write with load 1 index
When load 1 != load 2 due to concurrent modification, the base and
index are inconsistent, causing writes far outside the output buffer
(65400 bytes scratch buffer, actual write offset ~3.4MB).
Disable GCOV for all zlib code since it contains performance-critical
inner loops that execute concurrently from multiple CPUs.
https://virtuozzo.atlassian.net/browse/VSTOR-127788
Signed-off-by: Konstantin Khorenko <[email protected]>
Feature: fix ms/lib
---
lib/zlib_deflate/Makefile | 5 +++++
lib/zlib_dfltcc/Makefile | 5 +++++
lib/zlib_inflate/Makefile | 5 +++++
3 files changed, 15 insertions(+)
diff --git a/lib/zlib_deflate/Makefile b/lib/zlib_deflate/Makefile
index 2622e03c0b942..3734afcf5d53b 100644
--- a/lib/zlib_deflate/Makefile
+++ b/lib/zlib_deflate/Makefile
@@ -7,6 +7,11 @@
# decompression code.
#
+# GCOV instrumentation generates code that uses global counters as loop
+# indices. When multiple CPUs execute zlib concurrently, the shared
+# counters cause inconsistent loop bounds and out-of-bounds memory writes.
+GCOV_PROFILE := n
+
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate.o
zlib_deflate-objs := deflate.o deftree.o deflate_syms.o
diff --git a/lib/zlib_dfltcc/Makefile b/lib/zlib_dfltcc/Makefile
index 66e1c96387c40..2e27db82c791c 100644
--- a/lib/zlib_dfltcc/Makefile
+++ b/lib/zlib_dfltcc/Makefile
@@ -6,6 +6,11 @@
# This is the code for s390 zlib hardware support.
#
+# GCOV instrumentation generates code that uses global counters as loop
+# indices. When multiple CPUs execute zlib concurrently, the shared
+# counters cause inconsistent loop bounds and out-of-bounds memory writes.
+GCOV_PROFILE := n
+
obj-$(CONFIG_ZLIB_DFLTCC) += zlib_dfltcc.o
zlib_dfltcc-objs := dfltcc.o dfltcc_deflate.o dfltcc_inflate.o
diff --git a/lib/zlib_inflate/Makefile b/lib/zlib_inflate/Makefile
index 27327d3e9f541..b159d7bf27678 100644
--- a/lib/zlib_inflate/Makefile
+++ b/lib/zlib_inflate/Makefile
@@ -14,6 +14,11 @@
# uncompression can be done without blocking on allocation).
#
+# GCOV instrumentation generates code that uses global counters as loop
+# indices. When multiple CPUs execute zlib concurrently, the shared
+# counters cause inconsistent loop bounds and out-of-bounds memory writes.
+GCOV_PROFILE := n
+
obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o
zlib_inflate-objs := inffast.o inflate.o infutil.o \
--
2.43.0
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel