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:
Quentin Perret
2023-04-03 19:06:08 +00:00
parent dac17bb8f7
commit ccfe12aa18
4 changed files with 35 additions and 7 deletions

View File

@@ -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 */

View File

@@ -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

View File

@@ -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);

View File

@@ -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 */