Activate a registered VBS backend from a late_initcall, once plane-0 is otherwise up. Enabling is opt-in and requires two conditions: 1. the operator passes enable-kvm-planes=1 on the kernel command line, and 2. the boot image advertises a provisioned secure plane via /etc/Kconfig.kvm-planes containing CONFIG_VM_PLANES=y. When both hold, call the backend's init() to load the secure plane and register a reboot notifier that invokes shutdown() to unload it. --- security/vbs/core.c | 114 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/security/vbs/core.c b/security/vbs/core.c index 407d49a91b8f..c006b6d53a14 100644 --- a/security/vbs/core.c +++ b/security/vbs/core.c @@ -8,8 +8,15 @@ #include #include +#include +#include +#include #include #include +#include +#include +#include +#include static const struct vbs_ops *vbs_backend; static DEFINE_MUTEX(vbs_lock); @@ -54,3 +61,110 @@ int vbs_vtl_call(enum vbs_call_id id, return ops->vtl_call(id, arg, arg_size, resp, resp_size); } EXPORT_SYMBOL_GPL(vbs_vtl_call); + +/* ── enable after driver init ────────────────────────────────── */ + +/* + * A registered backend is only activated when two conditions hold: + * 1. the operator opts in on the kernel command line (enable-kvm-planes=1), + * and + * 2. the boot image advertises a provisioned secure plane via a plane + * configuration file that enables the expected option. + */ +#define VBS_KCONFIG_PATH "/etc/Kconfig.kvm-planes" +#define VBS_KCONFIG_TOKEN "CONFIG_VM_PLANES=y" + +static bool vbs_enable_requested; + +static int __init vbs_parse_enable_kvm_planes(char *str) +{ + bool val; + + /* Bare "enable-kvm-planes" (no value) means enabled. */ + if (!str || !*str) + vbs_enable_requested = true; + else if (!kstrtobool(str, &val)) + vbs_enable_requested = val; + return 0; +} +early_param("enable-kvm-planes", vbs_parse_enable_kvm_planes); + +static int vbs_reboot_notify(struct notifier_block *nb, unsigned long action, + void *data) +{ + const struct vbs_ops *ops = READ_ONCE(vbs_backend); + + if (ops && ops->shutdown) + ops->shutdown(); + return NOTIFY_DONE; +} + +static struct notifier_block vbs_reboot_nb = { + .notifier_call = vbs_reboot_notify, +}; + +/* Return true if VBS_KCONFIG_PATH exists and enables the plane config. */ +static bool __init vbs_plane_config_present(void) +{ + void *buf = NULL; + size_t sz = 0; + bool ok = false; + int ret; + + ret = kernel_read_file_from_path(VBS_KCONFIG_PATH, 0, &buf, SZ_1M, &sz, + READING_UNKNOWN); + if (ret < 0) { + pr_info("vbs: %s unavailable (%d); backend left idle\n", + VBS_KCONFIG_PATH, ret); + return false; + } + + if (buf && sz) + ok = strnstr(buf, VBS_KCONFIG_TOKEN, sz) != NULL; + vfree(buf); + + if (!ok) + pr_info("vbs: %s present but %s not set; backend left idle\n", + VBS_KCONFIG_PATH, VBS_KCONFIG_TOKEN); + return ok; +} + +/* + * Enable the registered backend after device drivers have initialised. + * Runs at late_initcall so the plane is loaded only once the plane-0 kernel + * is otherwise up, the operator requested it (enable-kvm-planes=1), and the + * boot image advertises a plane config. + */ +static int __init vbs_enable(void) +{ + const struct vbs_ops *ops = READ_ONCE(vbs_backend); + int ret; + + if (!ops) { + pr_debug("vbs: no backend registered; nothing to enable\n"); + return 0; + } + + if (!vbs_enable_requested) { + pr_info("vbs: enable-kvm-planes not set; backend \"%s\" left idle\n", + ops->name); + return 0; + } + + if (!vbs_plane_config_present()) + return 0; + + if (ops->init) { + ret = ops->init(); + if (ret) { + pr_warn("vbs: backend \"%s\" init failed (%d)\n", + ops->name, ret); + return 0; + } + } + + register_reboot_notifier(&vbs_reboot_nb); + pr_info("vbs: enabled backend \"%s\"\n", ops->name); + return 0; +} +late_initcall(vbs_enable); -- 2.55.0