Skip to content

Commit fc4d3a6

Browse files
committed
KVM: x86: Enforce use of EXPORT_SYMBOL_FOR_KVM_INTERNAL
Add a (gnarly) inline "script" in the Makefile to fail the build if there is EXPORT_SYMBOL_GPL or EXPORT_SYMBOL usage in virt/kvm or arch/x86/kvm beyond the known-good/expected exports for other modules. Remembering to use EXPORT_SYMBOL_FOR_KVM_INTERNAL is surprisingly difficult, and hoping to detect "bad" exports via code review is not a robust long-term strategy. Jump through a pile of hoops to coerce make into printing a human-friendly error message, with the offending files+lines cleanly separated. E.g. where <srctree> is the resolution of $(srctree), i.e. '.' for in-tree builds, and the absolute path for out-of-tree-builds: <srctree>/arch/x86/kvm/Makefile:97: *** ERROR *** found 2 unwanted occurrences of EXPORT_SYMBOL_GPL: <srctree>/arch/x86/kvm/x86.c:686:EXPORT_SYMBOL_GPL(__kvm_set_user_return_msr); <srctree>/arch/x86/kvm/x86.c:703:EXPORT_SYMBOL_GPL(kvm_set_user_return_msr); in directories: <srctree>/arch/x86/kvm <srctree>/virt/kvm Use EXPORT_SYMBOL_FOR_KVM_INTERNAL, not EXPORT_SYMBOL_GPL. Stop. and <srctree>/arch/x86/kvm/Makefile:98: *** ERROR *** found 1 unwanted occurrences of EXPORT_SYMBOL: <srctree>/arch/x86/kvm/x86.c:709:EXPORT_SYMBOL(kvm_get_user_return_msr); in directories: <srctree>/arch/x86/kvm <srctree>/virt/kvm Use EXPORT_SYMBOL_FOR_KVM_INTERNAL, not EXPORT_SYMBOL. Stop. Put the enforcement in x86's Makefile even though the rule itself applies to virt/kvm, as putting the enforcement in virt/kvm/Makefile.kvm would effectively require exempting every architecture except x86. PPC is the only other architecture with sub-modules, and PPC hasn't been switched to use EXPORT_SYMBOL_FOR_KVM_INTERNAL (and given its nearly-orphaned state, likely never will). And for KVM architectures without sub-modules, that means that, barring truly spurious exports, the exports are intended for non-KVM usage and thus shouldn't be using EXPORT_SYMBOL_FOR_KVM_INTERNAL. Tested-by: Chao Gao <chao.gao@intel.com> Link: https://patch.msgid.link/20251121190514.293385-1-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 57a7b47 commit fc4d3a6

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

arch/x86/kvm/Makefile

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,52 @@ $(obj)/kvm-asm-offsets.h: $(obj)/kvm-asm-offsets.s FORCE
4747

4848
targets += kvm-asm-offsets.s
4949
clean-files += kvm-asm-offsets.h
50+
51+
52+
# Fail the build if there is unexpected EXPORT_SYMBOL_GPL (or EXPORT_SYMBOL)
53+
# usage. All KVM-internal exports should use EXPORT_SYMBOL_FOR_KVM_INTERNAL.
54+
# Only a handful of exports intended for other modules (VFIO, KVMGT) should
55+
# use EXPORT_SYMBOL_GPL, and EXPORT_SYMBOL should never be used.
56+
ifdef CONFIG_KVM_X86
57+
# Search recursively for whole words and print line numbers. Filter out the
58+
# allowed set of exports, i.e. those that are intended for external usage.
59+
exports_grep_trailer := --include='*.[ch]' -nrw $(srctree)/virt/kvm $(srctree)/arch/x86/kvm | \
60+
grep -v -e kvm_page_track_register_notifier \
61+
-e kvm_page_track_unregister_notifier \
62+
-e kvm_write_track_add_gfn \
63+
-e kvm_write_track_remove_gfn \
64+
-e kvm_get_kvm \
65+
-e kvm_get_kvm_safe \
66+
-e kvm_put_kvm
67+
68+
# Force grep to emit a goofy group separator that can in turn be replaced with
69+
# the above newline macro (newlines in Make are a nightmare). Note, grep only
70+
# prints the group separator when N lines of context are requested via -C,
71+
# a.k.a. --NUM. Simply request zero lines. Print the separator only after
72+
# filtering out expected exports to avoid extra newlines in the error message.
73+
define get_kvm_exports
74+
$(shell grep "$(1)" -C0 $(exports_grep_trailer) | grep "$(1)" -C0 --group-separator="!SEP!")
75+
endef
76+
77+
define check_kvm_exports
78+
nr_kvm_exports := $(shell grep "$(1)" $(exports_grep_trailer) | wc -l)
79+
80+
ifneq (0,$$(nr_kvm_exports))
81+
$$(error ERROR ***\
82+
$$(newline)found $$(nr_kvm_exports) unwanted occurrences of $(1):\
83+
$$(newline) $(subst !SEP!,$$(newline) ,$(call get_kvm_exports,$(1)))\
84+
$$(newline)in directories:\
85+
$$(newline) $(srctree)/arch/x86/kvm\
86+
$$(newline) $(srctree)/virt/kvm\
87+
$$(newline)Use EXPORT_SYMBOL_FOR_KVM_INTERNAL, not $(1))
88+
endif # nr_kvm_exports != 0
89+
undefine nr_kvm_exports
90+
endef # check_kvm_exports
91+
92+
$(eval $(call check_kvm_exports,EXPORT_SYMBOL_GPL))
93+
$(eval $(call check_kvm_exports,EXPORT_SYMBOL))
94+
95+
undefine check_kvm_exports
96+
undefine get_kvm_exports
97+
undefine exports_grep_trailer
98+
endif # CONFIG_KVM_X86

0 commit comments

Comments
 (0)