[Devel] [PATCH vz10 v3] lib/zlib: use atomic GCOV counters to prevent crash in inflate_fast
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Fri Mar 27 18:58:42 MSK 2026
On 3/27/26 10:38, Vasileios Almpanis wrote:
> Reviewed-by: Vasileios Almpanis <vasileios.almpanis.virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
>
> On 3/26/26 6:50 PM, Konstantin Khorenko wrote:
>> GCC's GCOV instrumentation can merge global branch counters with loop
>> induction variables as an optimization. In inflate_fast(), the inner
>> copy loops get transformed so that the GCOV counter value is loaded
>> multiple times to compute the loop base address, start index, and end
>> bound. Since GCOV counters are global (not per-CPU), concurrent
>> execution on different CPUs causes the counter to change between loads,
>> producing inconsistent values and out-of-bounds memory writes.
>>
>> The crash manifests during IPComp (IP Payload Compression) processing
>> when inflate_fast() runs concurrently on multiple 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
>>
>> At the crash point, the compiler generated three loads from the same
>> global GCOV counter (__gcov0.inflate_fast+216) to compute base, start,
>> and end for an indexed loop. Another CPU modified the counter between
>> loads, making the values inconsistent — the write went 3.4 MB past a
>> 65 KB buffer.
>>
>> Add -fprofile-update=atomic to zlib Makefiles. This tells GCC that
>> GCOV counters may be concurrently accessed, causing counter updates to
>> use atomic instructions (lock addq) instead of plain load/store. This
>> prevents the compiler from merging counters with loop induction
>> variables. The flag is scoped to zlib only to avoid unnecessary
>> overhead in the rest of the kernel.
>>
>> https://virtuozzo.atlassian.net/browse/VSTOR-127788
>>
>> Feature: fix selftests
>> Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
>> ---
>> lib/zlib_deflate/Makefile | 6 ++++++
>> lib/zlib_dfltcc/Makefile | 6 ++++++
>> lib/zlib_inflate/Makefile | 7 +++++++
>> 3 files changed, 19 insertions(+)
>>
>> diff --git a/lib/zlib_deflate/Makefile b/lib/zlib_deflate/Makefile
>> index 2622e03c0b942..dc0b3e5660e9e 100644
>> --- a/lib/zlib_deflate/Makefile
>> +++ b/lib/zlib_deflate/Makefile
>> @@ -7,6 +7,12 @@
>> # decompression code.
>> #
>> +# Force atomic GCOV counter updates to prevent GCC from merging global
>> +# counters with loop induction variables (see lib/zlib_inflate/Makefile).
>> +ifdef CONFIG_GCOV_KERNEL
>> +ccflags-y += -fprofile-update=atomic
>> +endif
>> +
>> 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..fb08749d2ee7b 100644
>> --- a/lib/zlib_dfltcc/Makefile
>> +++ b/lib/zlib_dfltcc/Makefile
>> @@ -6,6 +6,12 @@
>> # This is the code for s390 zlib hardware support.
>> #
>> +# Force atomic GCOV counter updates to prevent GCC from merging global
>> +# counters with loop induction variables (see lib/zlib_inflate/Makefile).
>> +ifdef CONFIG_GCOV_KERNEL
>> +ccflags-y += -fprofile-update=atomic
>> +endif
>> +
>> 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..8707c649adda5 100644
>> --- a/lib/zlib_inflate/Makefile
>> +++ b/lib/zlib_inflate/Makefile
>> @@ -14,6 +14,13 @@
>> # uncompression can be done without blocking on allocation).
>> #
>> +# Force atomic GCOV counter updates to prevent GCC from merging global
>> +# counters with loop induction variables — concurrent inflate_fast()
>> +# execution on multiple CPUs causes out-of-bounds writes otherwise.
>> +ifdef CONFIG_GCOV_KERNEL
>> +ccflags-y += -fprofile-update=atomic
>> +endif
>> +
>> obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o
>> zlib_inflate-objs := inffast.o inflate.o infutil.o \
--
Best regards, Pavel Tikhomirov
Senior Software Developer, Virtuozzo.
More information about the Devel
mailing list