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

Reply via email to