tools/testing/selftests/kvm/Makefile.kvm | 1 + 1 file changed, 1 insertion(+)
Some distributions (such as Ubuntu) configure GCC so that
_FORTIFY_SOURCE is automatically enabled at -O1 or above. This results
in some fortified version of definitions of standard library functions
are included. While linker resolves the symbols, the fortified versions
might override the definitions in lib/string_override.c and reference to
those PLT entries in GLIBC. This is not a problem for the code in host,
but it is a disaster for the guest code. E.g., if build and run
x86/nested_emulation_test on Ubuntu 24.04 will encounter a L1 #PF due to
memset() reference to __memset_chk@plt.
The option -fno-builtin-memset is not helpful here, because those
fortified versions are not built-in but some definitions which are
included by header, they are for different intentions.
In order to eliminate the unpredictable behaviors may vary depending on
the linker and platform, add the "-U_FORTIFY_SOURCE" into CFLAGS to
prevent from introducing the fortified definitions.
Signed-off-by: Zhiquan Li <zhiquan_li@163.com>
---
tools/testing/selftests/kvm/Makefile.kvm | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index ba5c2b643efa..d45bf4ccb3bf 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -251,6 +251,7 @@ LINUX_TOOL_INCLUDE = $(top_srcdir)/tools/include
LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include
CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \
-Wno-gnu-variable-sized-type-not-at-end -MD -MP -DCONFIG_64BIT \
+ -U_FORTIFY_SOURCE \
-fno-builtin-memcmp -fno-builtin-memcpy \
-fno-builtin-memset -fno-builtin-strnlen \
-fno-stack-protector -fno-PIE -fno-strict-aliasing \
--
2.43.0
On Thu, 22 Jan 2026 13:35:50 +0800, Zhiquan Li wrote:
> Some distributions (such as Ubuntu) configure GCC so that
> _FORTIFY_SOURCE is automatically enabled at -O1 or above. This results
> in some fortified version of definitions of standard library functions
> are included. While linker resolves the symbols, the fortified versions
> might override the definitions in lib/string_override.c and reference to
> those PLT entries in GLIBC. This is not a problem for the code in host,
> but it is a disaster for the guest code. E.g., if build and run
> x86/nested_emulation_test on Ubuntu 24.04 will encounter a L1 #PF due to
> memset() reference to __memset_chk@plt.
>
> [...]
Applied to kvm-x86 fixes, thanks!
[1/1] KVM: selftests: Add -U_FORTIFY_SOURCE to avoid some unpredictable test failures
https://github.com/kvm-x86/linux/commit/e396a7422265
--
https://github.com/kvm-x86/linux/tree/next
On Thu, Jan 22, 2026, Zhiquan Li wrote: > Some distributions (such as Ubuntu) configure GCC so that > _FORTIFY_SOURCE is automatically enabled at -O1 or above. This results > in some fortified version of definitions of standard library functions > are included. While linker resolves the symbols, the fortified versions > might override the definitions in lib/string_override.c and reference to > those PLT entries in GLIBC. This is not a problem for the code in host, > but it is a disaster for the guest code. E.g., if build and run > x86/nested_emulation_test on Ubuntu 24.04 will encounter a L1 #PF due to > memset() reference to __memset_chk@plt. Ugh. I'm pretty sure I saw this recently as well (I forget what OS), and I was completely clueless as to why it was failing. Thanks a ton for tracking this down! > The option -fno-builtin-memset is not helpful here, because those > fortified versions are not built-in but some definitions which are > included by header, they are for different intentions. > > In order to eliminate the unpredictable behaviors may vary depending on > the linker and platform, add the "-U_FORTIFY_SOURCE" into CFLAGS to > prevent from introducing the fortified definitions. > > Signed-off-by: Zhiquan Li <zhiquan_li@163.com> > --- > tools/testing/selftests/kvm/Makefile.kvm | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm > index ba5c2b643efa..d45bf4ccb3bf 100644 > --- a/tools/testing/selftests/kvm/Makefile.kvm > +++ b/tools/testing/selftests/kvm/Makefile.kvm > @@ -251,6 +251,7 @@ LINUX_TOOL_INCLUDE = $(top_srcdir)/tools/include > LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include > CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \ > -Wno-gnu-variable-sized-type-not-at-end -MD -MP -DCONFIG_64BIT \ > + -U_FORTIFY_SOURCE \ Is this needed for _all_ code, or would it suffice to only disable fortification when building LIBKVM_STRING_OBJ? From the changelog description, it sounds like we need to disable fortification in the callers to prevent a redirect, but just in case I'm reading that wrong... > -fno-builtin-memcmp -fno-builtin-memcpy \ > -fno-builtin-memset -fno-builtin-strnlen \ > -fno-stack-protector -fno-PIE -fno-strict-aliasing \ > -- > 2.43.0 >
On 1/23/26 01:21, Sean Christopherson wrote:
> Is this needed for _all_ code, or would it suffice to only disable fortification
> when building LIBKVM_STRING_OBJ? From the changelog description, it sounds like
> we need to disable fortification in the callers to prevent a redirect, but just
> in case I'm reading that wrong...
Thanks for your review, Sean.
Unfortunately, disabling fortification only when building LIBKVM_STRING_OBJ is
insufficient, because the definitions of the fortified versions are included by
each caller during the preprocessing stage. I’ve done further investigation and
found the off tracking since compilation stage with the GCC “-c -fdump-tree-all”
options:
I found memset() is replaced by __builtin___memset_chk in
x86/nested_emulation_test.c.031t.einline phase by compiler and kept to the end.
At last, __builtin___memset_chk was redirected to __memset_chk@plt at GLIBC in
linking stage.
As a perfect reference substance, guest_memfd_test, which invokes memset() in
guest_code() as well. I replayed the same steps and found memset() is replaced
by __builtin___memset_chk in guest_memfd_test.c.031t.einline phase, but, it was
redirect to __builtin_memset in guest_memfd_test.c.103t.objsz1 phase after the
compiler computing maximum dynamic object size for the destination. Eventually,
__builtin_memset was redirected to memset at lib/string_override.o in linking stage.
Whatever, the KVM selftests guest code should not reference to the fortified
versions of string functions, let’s stop it at the beginning to avoid the
compiler dancing :-) Indeed, disabling fortification for all code may seem
overly aggressive. We can first try limiting the scope to
x86/nested_emulation_test and then expand the blast radius if the similar issues
arise in other files in the future.
The new patch as below:
---
From 33b502ea1cf6f4b6ac272bda64e1361903330d61 Mon Sep 17 00:00:00 2001
From: Zhiquan Li <zhiquan_li@163.com>
Date: Fri, 23 Jan 2026 17:05:41 +0800
Subject: [PATCH] KVM: selftests: Add -U_FORTIFY_SOURCE to avoid
x86/nested_emulation_test failed
Some distributions (such as Ubuntu) configure GCC so that
_FORTIFY_SOURCE is automatically enabled at -O1 or above. This results
in some fortified version of definitions of standard library functions
are included. While compiler parsers the symbols, the string functions
might be replaced by the fortified versions, this will result in the
definitions in lib/string_override.c are skipped and reference to those
PLT entries in GLIBC in by linker. This is not a problem for the code
in host, but it is a disaster for the guest code. E.g., if build and
run x86/nested_emulation_test on Ubuntu 24.04 will encounter a L1 #PF
due to memset() reference to __memset_chk@plt.
The option -fno-builtin-memset is not helpful here, because those
fortified versions are not built-in but some definitions which are
included by header, they are for different intentions.
In order to eliminate the unpredictable behaviors may vary depending on
the compiler and platform, add "-U_FORTIFY_SOURCE" into CFLAGS for
x86/nested_emulation_test to prevent from introducing the fortified
definitions.
Signed-off-by: Zhiquan Li <zhiquan_li@163.com>
---
tools/testing/selftests/kvm/Makefile.kvm | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/testing/selftests/kvm/Makefile.kvm
b/tools/testing/selftests/kvm/Makefile.kvm
index ba5c2b643efa..5fd35d593023 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -282,6 +282,8 @@ $(GEN_HDRS): $(wildcard $(arm64_tools_dir)/*)
$(MAKE) -C $(arm64_tools_dir) OUTPUT=$(arm64_hdr_outdir)
endif
+$(OUTPUT)/x86/nested_emulation_test.o: CFLAGS += -U_FORTIFY_SOURCE
+
no-pie-option := $(call try-run, echo 'int main(void) { return 0; }' | \
$(CC) -Werror $(CFLAGS) -no-pie -x c - -o "$$TMP", -no-pie)
--
2.43.0
On Fri, Jan 23, 2026, Zhiquan Li wrote: > > On 1/23/26 01:21, Sean Christopherson wrote: > > Is this needed for _all_ code, or would it suffice to only disable fortification > > when building LIBKVM_STRING_OBJ? From the changelog description, it sounds like > > we need to disable fortification in the callers to prevent a redirect, but just > > in case I'm reading that wrong... > > Thanks for your review, Sean. > > Unfortunately, disabling fortification only when building LIBKVM_STRING_OBJ is > insufficient, because the definitions of the fortified versions are included by > each caller during the preprocessing stage. I’ve done further investigation and > found the off tracking since compilation stage with the GCC “-c -fdump-tree-all” > options: > > I found memset() is replaced by __builtin___memset_chk in > x86/nested_emulation_test.c.031t.einline phase by compiler and kept to the end. > At last, __builtin___memset_chk was redirected to __memset_chk@plt at GLIBC in > linking stage. > > As a perfect reference substance, guest_memfd_test, which invokes memset() in > guest_code() as well. I replayed the same steps and found memset() is replaced > by __builtin___memset_chk in guest_memfd_test.c.031t.einline phase, but, it was > redirect to __builtin_memset in guest_memfd_test.c.103t.objsz1 phase after the > compiler computing maximum dynamic object size for the destination. Eventually, > __builtin_memset was redirected to memset at lib/string_override.o in linking stage. > > Whatever, the KVM selftests guest code should not reference to the fortified > versions of string functions, let’s stop it at the beginning to avoid the > compiler dancing :-) Indeed, disabling fortification for all code may seem > overly aggressive. Nah, that'll just turn into a game of whack-a-mole, and likely with extremely random moles :-) I verified the original patch fixes my problematic setup, I'll get it queued up. Thanks!
© 2016 - 2026 Red Hat, Inc.