mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
ANDROID: KVM: arm64: Restrict pKVM hyp exports
The pKVM hypervisor uses the module_ops struct as a way to expose services to loadable modules. It doesn't however allow fine-grained definition of the license for each export, and doesn't have a way to check the license of the loaded module (yet). As such, the assumption is that said module is proprietary, and must NOT be allowed to use GPL symbols. Even though symbols such as __pkvm_load_el2_module are currently exported as GPL, these exports only apply to the kernel part of the module, which is usually only a proxy to load the hyp module, which may be built separately. Given the lack of license enforcement at load time, let's seek GPL compliance by preventing the accidental export of GPL symbols to hyp modules via pKVM's module_ops struct. To do so, add a build time check for the absence of such symbols from the KVM nvhe code entirely. In the future (Android 15+ and upstream), we should consider expanding the pKVM module loader to allow finer grained licensing of exports. This would allow exposing internal pKVM functions as GPL only for e.g. selftests and such w/o risking exports to proprietary modules. Bug: 263340138 Bug: 267430896 Change-Id: I09b81bfe322c0d2746c0349c5f217a5a76b6e33d Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
@@ -921,4 +921,19 @@ alternative_cb ARM64_ALWAYS_SYSTEM, spectre_bhb_patch_clearbhb
|
||||
alternative_cb_end
|
||||
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
|
||||
.endm
|
||||
|
||||
#if defined(__KVM_NVHE_HYPERVISOR__)
|
||||
/*
|
||||
* pKVM uses the module_ops struct to expose services to modules but
|
||||
* doesn't allow fine-grained definition of the license for each export,
|
||||
* and doesn't have a way to check the license of the loaded module.
|
||||
* Given that said module may be proprietary, let's seek GPL compliance
|
||||
* by preventing the accidental export of GPL symbols to hyp modules via
|
||||
* pKVM's module_ops struct.
|
||||
*/
|
||||
#ifdef EXPORT_SYMBOL_GPL
|
||||
#undef EXPORT_SYMBOL_GPL
|
||||
#endif
|
||||
#define EXPORT_SYMBOL_GPL(sym) ASM_BUILD_BUG()
|
||||
#endif
|
||||
#endif /* __ASM_ASSEMBLER_H */
|
||||
|
||||
@@ -159,6 +159,19 @@ extern void *__nvhe_undefined_symbol;
|
||||
#define this_cpu_ptr_hyp_sym(sym) (&__nvhe_undefined_symbol)
|
||||
#define per_cpu_ptr_hyp_sym(sym, cpu) (&__nvhe_undefined_symbol)
|
||||
|
||||
/*
|
||||
* pKVM uses the module_ops struct to expose services to modules but
|
||||
* doesn't allow fine-grained definition of the license for each export,
|
||||
* and doesn't have a way to check the license of the loaded module.
|
||||
* Given that said module may be proprietary, let's seek GPL compliance
|
||||
* by preventing the accidental export of GPL symbols to hyp modules via
|
||||
* pKVM's module_ops struct.
|
||||
*/
|
||||
#ifdef EXPORT_SYMBOL_GPL
|
||||
#undef EXPORT_SYMBOL_GPL
|
||||
#endif
|
||||
#define EXPORT_SYMBOL_GPL(sym) BUILD_BUG()
|
||||
|
||||
#elif defined(__KVM_VHE_HYPERVISOR__)
|
||||
|
||||
#define CHOOSE_VHE_SYM(sym) sym
|
||||
|
||||
@@ -16,7 +16,7 @@ int pkvm_iommu_driver_init(u64 drv, void *data, size_t size)
|
||||
{
|
||||
return kvm_call_hyp_nvhe(__pkvm_iommu_driver_init, drv, data, size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pkvm_iommu_driver_init);
|
||||
EXPORT_SYMBOL(pkvm_iommu_driver_init);
|
||||
|
||||
int pkvm_iommu_register(struct device *dev, u64 drv, phys_addr_t pa,
|
||||
size_t size, struct device *parent, u8 flags)
|
||||
@@ -41,24 +41,24 @@ int pkvm_iommu_register(struct device *dev, u64 drv, phys_addr_t pa,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pkvm_iommu_register);
|
||||
EXPORT_SYMBOL(pkvm_iommu_register);
|
||||
|
||||
int pkvm_iommu_suspend(struct device *dev)
|
||||
{
|
||||
return kvm_call_hyp_nvhe(__pkvm_iommu_pm_notify, dev_to_id(dev),
|
||||
PKVM_IOMMU_PM_SUSPEND);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pkvm_iommu_suspend);
|
||||
EXPORT_SYMBOL(pkvm_iommu_suspend);
|
||||
|
||||
int pkvm_iommu_resume(struct device *dev)
|
||||
{
|
||||
return kvm_call_hyp_nvhe(__pkvm_iommu_pm_notify, dev_to_id(dev),
|
||||
PKVM_IOMMU_PM_RESUME);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pkvm_iommu_resume);
|
||||
EXPORT_SYMBOL(pkvm_iommu_resume);
|
||||
|
||||
int pkvm_iommu_finalize(int err)
|
||||
{
|
||||
return kvm_call_hyp_nvhe(__pkvm_iommu_finalize, err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pkvm_iommu_finalize);
|
||||
EXPORT_SYMBOL(pkvm_iommu_finalize);
|
||||
|
||||
@@ -870,11 +870,11 @@ int __pkvm_load_el2_module(struct module *this, unsigned long *token)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__pkvm_load_el2_module);
|
||||
EXPORT_SYMBOL(__pkvm_load_el2_module);
|
||||
|
||||
int __pkvm_register_el2_call(unsigned long hfn_hyp_va)
|
||||
{
|
||||
return kvm_call_hyp_nvhe(__pkvm_register_hcall, hfn_hyp_va);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__pkvm_register_el2_call);
|
||||
EXPORT_SYMBOL(__pkvm_register_el2_call);
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
Reference in New Issue
Block a user