- Add support for the 'bhyve:///session' connection URL for running in unprivileged mode. - Use bhyve monitor mode ('-M') and a per-user runtime directory. - Require monitor mode and VM PID query support for session mode. - Use user configuration directories instead of system-wide directories. Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com> --- src/bhyve/bhyve_command.c | 7 ++++++ src/bhyve/bhyve_conf.c | 42 ++++++++++++++++++++++++++--------- src/bhyve/bhyve_conf.h | 2 +- src/bhyve/bhyve_domain.c | 9 +++++++- src/bhyve/bhyve_driver.c | 46 ++++++++++++++++++++++++++------------- src/bhyve/bhyve_process.c | 2 +- src/bhyve/bhyve_utils.h | 2 ++ tests/bhyvexml2argvtest.c | 4 +++- tests/bhyvexml2xmltest.c | 2 +- 9 files changed, 86 insertions(+), 30 deletions(-) diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index f0a87cffea..41c3767c3e 100644 --- a/src/bhyve/bhyve_command.c +++ b/src/bhyve/bhyve_command.c @@ -1100,6 +1100,13 @@ virBhyveProcessBuildBhyveCmd(struct _bhyveConn *driver, virDomainDef *def, unsigned nvcpus = virDomainDefGetVcpus(def); size_t ncells = virDomainNumaGetNodeCount(def->numa); + /* Monitor mode */ + if (!driver->privileged) { + virCommandAddArg(cmd, "-M"); + virCommandAddArg(cmd, "-o"); + virCommandAddArgFormat(cmd, "rundir=%s", driver->config->stateDir); + } + /* CPUs */ virCommandAddArg(cmd, "-c"); if (def->cpu && def->cpu->sockets) { diff --git a/src/bhyve/bhyve_conf.c b/src/bhyve/bhyve_conf.c index e0439af6fa..182dd24a60 100644 --- a/src/bhyve/bhyve_conf.c +++ b/src/bhyve/bhyve_conf.c @@ -25,6 +25,7 @@ #include "viralloc.h" #include "virlog.h" #include "virstring.h" +#include "virutil.h" #include "bhyve_conf.h" #include "bhyve_domain.h" #include "configmake.h" @@ -47,7 +48,7 @@ static int virBhyveConfigOnceInit(void) VIR_ONCE_GLOBAL_INIT(virBhyveConfig); struct _virBhyveDriverConfig * -virBhyveDriverConfigNew(void) +virBhyveDriverConfigNew(bool privileged) { struct _virBhyveDriverConfig *cfg; @@ -57,18 +58,39 @@ virBhyveDriverConfigNew(void) if (!(cfg = virObjectNew(virBhyveDriverConfigClass))) return NULL; - cfg->configBaseDir = g_strdup(SYSCONFDIR "/libvirt"); + if (privileged) { + cfg->configBaseDir = g_strdup(SYSCONFDIR "/libvirt"); - cfg->firmwareDir = g_strdup(DATADIR "/uefi-firmware"); - cfg->libDir = g_strdup_printf("%s/lib/libvirt/bhyve", LOCALSTATEDIR); - cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir); + cfg->firmwareDir = g_strdup(DATADIR "/uefi-firmware"); + cfg->libDir = g_strdup_printf("%s/lib/libvirt/bhyve", LOCALSTATEDIR); + cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir); - cfg->ubootPath = g_strdup(DATADIR "/u-boot/u-boot-bhyve-arm64/u-boot.bin"); + cfg->ubootPath = g_strdup(DATADIR "/u-boot/u-boot-bhyve-arm64/u-boot.bin"); - cfg->configDir = g_strdup_printf("%s/bhyve", cfg->configBaseDir); - cfg->autostartDir = g_strdup_printf("%s/bhyve/autostart", cfg->configBaseDir); - cfg->stateDir = g_strdup_printf("%s/libvirt/bhyve", RUNSTATEDIR); - cfg->logDir = g_strdup_printf("%s/log/libvirt/bhyve", LOCALSTATEDIR); + cfg->configDir = g_strdup_printf("%s/bhyve", cfg->configBaseDir); + cfg->autostartDir = g_strdup_printf("%s/bhyve/autostart", cfg->configBaseDir); + cfg->stateDir = g_strdup_printf("%s/libvirt/bhyve", RUNSTATEDIR); + cfg->logDir = g_strdup_printf("%s/log/libvirt/bhyve", LOCALSTATEDIR); + } else { + g_autofree char *rundir = NULL; + g_autofree char *cachedir = NULL; + + cfg->configBaseDir = virGetUserConfigDirectory(); + + cachedir = virGetUserCacheDirectory(); + rundir = virGetUserRuntimeDirectory(); + + cfg->firmwareDir = g_strdup(DATADIR "/uefi-firmware"); + cfg->libDir = g_strdup_printf("%s/bhyve/lib", cfg->configBaseDir); + cfg->nvramDir = g_strdup_printf("%s/bhyve/nvram", cfg->configBaseDir); + + cfg->ubootPath = g_strdup(DATADIR "/u-boot/u-boot-bhyve-arm64/u-boot.bin"); + + cfg->configDir = g_strdup_printf("%s/bhyve", cfg->configBaseDir); + cfg->autostartDir = g_strdup_printf("%s/bhyve/autostart", cfg->configBaseDir); + cfg->stateDir = g_strdup_printf("%s/bhyve/run", rundir); + cfg->logDir = g_strdup_printf("%s/bhyve/log", cachedir); + } cfg->bhyveloadTimeout = 300; cfg->bhyveloadTimeoutKill = 15; diff --git a/src/bhyve/bhyve_conf.h b/src/bhyve/bhyve_conf.h index d895f66bb7..70c6b1f6ed 100644 --- a/src/bhyve/bhyve_conf.h +++ b/src/bhyve/bhyve_conf.h @@ -23,7 +23,7 @@ #include "bhyve_utils.h" -struct _virBhyveDriverConfig *virBhyveDriverConfigNew(void); +struct _virBhyveDriverConfig *virBhyveDriverConfigNew(bool privileged); struct _virBhyveDriverConfig *virBhyveDriverGetConfig(struct _bhyveConn *driver); int virBhyveLoadDriverConfig(struct _virBhyveDriverConfig *cfg, const char *filename); diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c index 3588557979..2513573e98 100644 --- a/src/bhyve/bhyve_domain.c +++ b/src/bhyve/bhyve_domain.c @@ -555,9 +555,10 @@ bhyveValidateDomainLifecycleAction(const virDomainDef *def) static int bhyveDomainDefValidate(const virDomainDef *def, - void *opaque G_GNUC_UNUSED, + void *opaque, void *parseOpaque G_GNUC_UNUSED) { + struct _bhyveConn *driver = opaque; size_t i; size_t ncells; virStorageSource *src = NULL; @@ -640,6 +641,12 @@ bhyveDomainDefValidate(const virDomainDef *def, return -1; } + if (!driver->privileged && !def->os.loader) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("only UEFI boot is supported in unprivileged mode")); + return -1; + } + if (bhyveValidateDomainLifecycleAction(def) < 0) return -1; diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c index 7e8cc572e4..f48543e205 100644 --- a/src/bhyve/bhyve_driver.c +++ b/src/bhyve/bhyve_driver.c @@ -211,7 +211,8 @@ bhyveConnectURIProbe(char **uri) if (bhyve_driver == NULL) return 0; - *uri = g_strdup("bhyve:///system"); + *uri = g_strdup(bhyve_driver->privileged ? + "bhyve:///system" : "bhyve:///session"); return 1; } @@ -224,19 +225,17 @@ bhyveConnectOpen(virConnectPtr conn, { virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); - if (STRNEQ(conn->uri->path, "/system")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unexpected bhyve URI path '%1$s', try bhyve:///system"), - conn->uri->path); - return VIR_DRV_OPEN_ERROR; - } - if (bhyve_driver == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("bhyve state driver is not active")); return VIR_DRV_OPEN_ERROR; } + if (!virConnectValidateURIPath(conn->uri->path, + "bhyve", + bhyve_driver->privileged)) + return VIR_DRV_OPEN_ERROR; + if (virConnectOpenEnsureACL(conn) < 0) return VIR_DRV_OPEN_ERROR; @@ -1398,6 +1397,7 @@ bhyveStateInitialize(bool privileged, void *opaque G_GNUC_UNUSED) { virDomainDriverAutoStartConfig autostartCfg; + g_autofree char *configFile = NULL; virBhyveDriverConfig *cfg; if (root != NULL) { @@ -1406,13 +1406,9 @@ bhyveStateInitialize(bool privileged, return -1; } - if (!privileged) { - VIR_INFO("Not running privileged, disabling driver"); - return VIR_DRV_STATE_INIT_SKIPPED; - } - bhyve_driver = g_new0(bhyveConn, 1); + bhyve_driver->privileged = privileged; bhyve_driver->lockFD = -1; if (virMutexInit(&bhyve_driver->lock) < 0) { VIR_FREE(bhyve_driver); @@ -1425,6 +1421,18 @@ bhyveStateInitialize(bool privileged, if (virBhyveProbeCaps(&bhyve_driver->bhyvecaps) < 0) goto cleanup; + if (!privileged && !(bhyveDriverGetBhyveCaps(bhyve_driver) & BHYVE_CAP_MONITOR)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("bhyve does not support monitor mode, cannot run unprivileged")); + goto cleanup; + } + + if (!privileged && !(bhyveDriverGetBhyveCaps(bhyve_driver) & BHYVE_CAP_GET_VMPID)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("bhyvectl does not support querying the VM PID, cannot run unprivileged")); + goto cleanup; + } + if (virBhyveProbeGrubCaps(&bhyve_driver->grubcaps) < 0) goto cleanup; @@ -1443,10 +1451,11 @@ bhyveStateInitialize(bool privileged, bhyve_driver->hostsysinfo = virSysinfoRead(); - if (!(bhyve_driver->config = cfg = virBhyveDriverConfigNew())) + if (!(bhyve_driver->config = cfg = virBhyveDriverConfigNew(privileged))) goto cleanup; - if (virBhyveLoadDriverConfig(bhyve_driver->config, SYSCONFDIR "/libvirt/bhyve.conf") < 0) + configFile = g_build_filename(cfg->configBaseDir, "bhyve.conf", NULL); + if (virBhyveLoadDriverConfig(cfg, configFile) < 0) goto cleanup; if (g_mkdir_with_parents(cfg->logDir, 0777) < 0) { @@ -1463,6 +1472,13 @@ bhyveStateInitialize(bool privileged, goto cleanup; } + if (g_mkdir_with_parents(cfg->nvramDir, 0777) < 0) { + virReportSystemError(errno, + _("Failed to mkdir %1$s"), + cfg->nvramDir); + goto cleanup; + } + if ((bhyve_driver->lockFD = virPidFileAcquire(cfg->stateDir, "driver", getpid())) < 0) goto cleanup; diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c index 4144f8230e..c42d9ec092 100644 --- a/src/bhyve/bhyve_process.c +++ b/src/bhyve/bhyve_process.c @@ -537,7 +537,7 @@ bhyvePrepareNVRAMFile(bhyveConn *driver G_GNUC_UNUSED, if (virFileRewrite(loader->nvram->path, S_IRUSR | S_IWUSR, - 0, 0, + -1, -1, bhyvePrepareNVRAMHelper, &data) < 0) { return -1; diff --git a/src/bhyve/bhyve_utils.h b/src/bhyve/bhyve_utils.h index 5d04b42195..8a6ca25b47 100644 --- a/src/bhyve/bhyve_utils.h +++ b/src/bhyve/bhyve_utils.h @@ -70,6 +70,8 @@ struct _bhyveConn { unsigned bhyvecaps; unsigned grubcaps; + + bool privileged; }; typedef struct _bhyveConn bhyveConn; diff --git a/tests/bhyvexml2argvtest.c b/tests/bhyvexml2argvtest.c index 95969a641b..06af9dec8a 100644 --- a/tests/bhyvexml2argvtest.c +++ b/tests/bhyvexml2argvtest.c @@ -162,7 +162,7 @@ mymain(void) if (!(driver.remotePorts = virPortAllocatorRangeNew("display", 5900, 65535))) return EXIT_FAILURE; - if (!(driver.config = virBhyveDriverConfigNew())) + if (!(driver.config = virBhyveDriverConfigNew(true))) return EXIT_FAILURE; VIR_FREE(driver.config->firmwareDir); @@ -174,6 +174,8 @@ mymain(void) driver.config->bhyveloadTimeout = 0; driver.config->bhyveloadTimeoutKill = 0; + driver.privileged = true; + # define DO_TEST_FULL(name, flags) \ do { \ static struct testInfo info = { \ diff --git a/tests/bhyvexml2xmltest.c b/tests/bhyvexml2xmltest.c index 336278ce1c..92710b3f0f 100644 --- a/tests/bhyvexml2xmltest.c +++ b/tests/bhyvexml2xmltest.c @@ -67,7 +67,7 @@ mymain(void) if ((driver.xmlopt = virBhyveDriverCreateXMLConf(&driver)) == NULL) return EXIT_FAILURE; - if (!(driver.config = virBhyveDriverConfigNew())) + if (!(driver.config = virBhyveDriverConfigNew(true))) return EXIT_FAILURE; VIR_FREE(driver.config->firmwareDir); -- 2.55.0