static int virNetSocketForkDaemon(const char *binary) { int ret; virCommandPtr cmd = virCommandNewArgList(binary, "--timeout=30", NULL); virCommandAddEnvPassCommon(cmd); virCommandClearCaps(cmd); virCommandDaemonize(cmd); ret = virCommandRun(cmd, NULL); virCommandFree(cmd); return ret; }
int qemuCapsProbeCPUModels(const char *qemu, virBitmapPtr qemuCaps, const char *arch, unsigned int *count, const char ***cpus) { char *output = NULL; int ret = -1; qemuCapsParseCPUModels parse; virCommandPtr cmd; if (count) *count = 0; if (cpus) *cpus = NULL; if (STREQ(arch, "i686") || STREQ(arch, "x86_64")) parse = qemuCapsParseX86Models; else if (STREQ(arch, "ppc64")) parse = qemuCapsParsePPCModels; else { VIR_DEBUG("don't know how to parse %s CPU models", arch); return 0; } cmd = virCommandNewArgList(qemu, "-cpu", "?", NULL); if (qemuCapsGet(qemuCaps, QEMU_CAPS_NODEFCONFIG)) virCommandAddArg(cmd, "-nodefconfig"); virCommandAddEnvPassCommon(cmd); virCommandSetOutputBuffer(cmd, &output); virCommandClearCaps(cmd); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (parse(output, count, cpus) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(output); virCommandFree(cmd); return ret; }
int qemuCapsProbeMachineTypes(const char *binary, virCapsGuestMachinePtr **machines, int *nmachines) { char *output; int ret = -1; virCommandPtr cmd; int status; /* Make sure the binary we are about to try exec'ing exists. * Technically we could catch the exec() failure, but that's * in a sub-process so it's hard to feed back a useful error. */ if (!virFileIsExecutable(binary)) { virReportSystemError(errno, _("Cannot find QEMU binary %s"), binary); return -1; } cmd = virCommandNewArgList(binary, "-M", "?", NULL); virCommandAddEnvPassCommon(cmd); virCommandSetOutputBuffer(cmd, &output); virCommandClearCaps(cmd); /* Ignore failure from older qemu that did not understand '-M ?'. */ if (virCommandRun(cmd, &status) < 0) goto cleanup; if (qemuCapsParseMachineTypesStr(output, machines, nmachines) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(output); virCommandFree(cmd); return ret; }
/** * qemuCreateInBridgePortWithHelper: * @cfg: the configuration object in which the helper name is looked up * @brname: the bridge name * @ifname: the returned interface name * @macaddr: the returned MAC address * @tapfd: file descriptor return value for the new tap device * @flags: OR of virNetDevTapCreateFlags: * VIR_NETDEV_TAP_CREATE_VNET_HDR * - Enable IFF_VNET_HDR on the tap device * * This function creates a new tap device on a bridge using an external * helper. The final name for the bridge will be stored in @ifname. * * Returns 0 in case of success or -1 on failure */ static int qemuCreateInBridgePortWithHelper(virQEMUDriverConfigPtr cfg, const char *brname, char **ifname, int *tapfd, unsigned int flags) { virCommandPtr cmd; char *errbuf = NULL, *cmdstr = NULL; int pair[2] = { -1, -1 }; if ((flags & ~VIR_NETDEV_TAP_CREATE_VNET_HDR) != VIR_NETDEV_TAP_CREATE_IFUP) return -1; if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) { virReportSystemError(errno, "%s", _("failed to create socket")); return -1; } if (!virFileIsExecutable(cfg->bridgeHelperName)) { virReportSystemError(errno, _("'%s' is not a suitable bridge helper"), cfg->bridgeHelperName); return -1; } cmd = virCommandNew(cfg->bridgeHelperName); if (flags & VIR_NETDEV_TAP_CREATE_VNET_HDR) virCommandAddArgFormat(cmd, "--use-vnet"); virCommandAddArgFormat(cmd, "--br=%s", brname); virCommandAddArgFormat(cmd, "--fd=%d", pair[1]); virCommandSetErrorBuffer(cmd, &errbuf); virCommandDoAsyncIO(cmd); virCommandPassFD(cmd, pair[1], VIR_COMMAND_PASS_FD_CLOSE_PARENT); virCommandClearCaps(cmd); #ifdef CAP_NET_ADMIN virCommandAllowCap(cmd, CAP_NET_ADMIN); #endif if (virCommandRunAsync(cmd, NULL) < 0) { *tapfd = -1; goto cleanup; } do { *tapfd = recvfd(pair[0], 0); } while (*tapfd < 0 && errno == EINTR); if (*tapfd < 0) { char ebuf[1024]; char *errstr = NULL; if (!(cmdstr = virCommandToString(cmd))) goto cleanup; virCommandAbort(cmd); if (errbuf && *errbuf && virAsprintf(&errstr, "\nstderr=%s", errbuf) < 0) goto cleanup; virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: failed to communicate with bridge helper: %s%s"), cmdstr, virStrerror(errno, ebuf, sizeof(ebuf)), errstr ? errstr : ""); VIR_FREE(errstr); goto cleanup; } if (virNetDevTapGetName(*tapfd, ifname) < 0 || virCommandWait(cmd, NULL) < 0) { VIR_FORCE_CLOSE(*tapfd); *tapfd = -1; } cleanup: VIR_FREE(cmdstr); VIR_FREE(errbuf); virCommandFree(cmd); VIR_FORCE_CLOSE(pair[0]); return *tapfd < 0 ? -1 : 0; }
static int dnsmasqCapsRefreshInternal(dnsmasqCapsPtr caps, bool force) { int ret = -1; struct stat sb; virCommandPtr cmd = NULL; char *help = NULL, *version = NULL, *complete = NULL; if (!caps || caps->noRefresh) return 0; if (stat(caps->binaryPath, &sb) < 0) { virReportSystemError(errno, _("Cannot check dnsmasq binary %s"), caps->binaryPath); return -1; } if (!force && caps->mtime == sb.st_mtime) return 0; caps->mtime = sb.st_mtime; /* Make sure the binary we are about to try exec'ing exists. * Technically we could catch the exec() failure, but that's * in a sub-process so it's hard to feed back a useful error. */ if (!virFileIsExecutable(caps->binaryPath)) { virReportSystemError(errno, _("dnsmasq binary %s is not executable"), caps->binaryPath); goto cleanup; } cmd = virCommandNewArgList(caps->binaryPath, "--version", NULL); virCommandSetOutputBuffer(cmd, &version); virCommandAddEnvPassCommon(cmd); virCommandClearCaps(cmd); if (virCommandRun(cmd, NULL) < 0) { virReportSystemError(errno, _("failed to run '%s --version': %s"), caps->binaryPath, version); goto cleanup; } virCommandFree(cmd); cmd = virCommandNewArgList(caps->binaryPath, "--help", NULL); virCommandSetOutputBuffer(cmd, &help); virCommandAddEnvPassCommon(cmd); virCommandClearCaps(cmd); if (virCommandRun(cmd, NULL) < 0) { virReportSystemError(errno, _("failed to run '%s --help': %s"), caps->binaryPath, help); goto cleanup; } if (virAsprintf(&complete, "%s\n%s", version, help) < 0) goto cleanup; ret = dnsmasqCapsSetFromBuffer(caps, complete); cleanup: virCommandFree(cmd); VIR_FREE(help); VIR_FREE(version); VIR_FREE(complete); return ret; }
/* * qemuTPMEmulatorBuildCommand: * * @tpm: TPM definition * @vmname: The name of the VM * @vmuuid: The UUID of the VM * @privileged: whether we are running in privileged mode * @swtpm_user: The uid for the swtpm to run as (drop privileges to from root) * @swtpm_group: The gid for the swtpm to run as * @swtpmStateDir: the directory where swtpm writes the pid file and creates the * Unix socket * @shortName: the short name of the VM * * Create the virCommand use for starting the emulator * Do some initializations on the way, such as creation of storage * and emulator setup. */ static virCommandPtr qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm, const char *vmname, const unsigned char *vmuuid, bool privileged, uid_t swtpm_user, gid_t swtpm_group, const char *swtpmStateDir, const char *shortName) { virCommandPtr cmd = NULL; bool created = false; char *pidfile; if (qemuTPMCreateEmulatorStorage(tpm->data.emulator.storagepath, &created, swtpm_user, swtpm_group) < 0) return NULL; if (created && qemuTPMEmulatorRunSetup(tpm->data.emulator.storagepath, vmname, vmuuid, privileged, swtpm_user, swtpm_group, tpm->data.emulator.logfile, tpm->version) < 0) goto error; unlink(tpm->data.emulator.source.data.nix.path); cmd = virCommandNew(swtpm_path); if (!cmd) goto error; virCommandClearCaps(cmd); virCommandAddArgList(cmd, "socket", "--daemon", "--ctrl", NULL); virCommandAddArgFormat(cmd, "type=unixio,path=%s,mode=0600", tpm->data.emulator.source.data.nix.path); virCommandAddArg(cmd, "--tpmstate"); virCommandAddArgFormat(cmd, "dir=%s,mode=0600", tpm->data.emulator.storagepath); virCommandAddArg(cmd, "--log"); virCommandAddArgFormat(cmd, "file=%s", tpm->data.emulator.logfile); virCommandSetUID(cmd, swtpm_user); virCommandSetGID(cmd, swtpm_group); switch (tpm->version) { case VIR_DOMAIN_TPM_VERSION_1_2: break; case VIR_DOMAIN_TPM_VERSION_2_0: virCommandAddArg(cmd, "--tpm2"); break; case VIR_DOMAIN_TPM_VERSION_DEFAULT: case VIR_DOMAIN_TPM_VERSION_LAST: break; } if (!(pidfile = qemuTPMEmulatorCreatePidFilename(swtpmStateDir, shortName))) goto error; virCommandAddArg(cmd, "--pid"); virCommandAddArgFormat(cmd, "file=%s", pidfile); VIR_FREE(pidfile); return cmd; error: if (created) qemuTPMDeleteEmulatorStorage(tpm); virCommandFree(cmd); return NULL; }
/* * qemuTPMEmulatorRunSetup * * @storagepath: path to the directory for TPM state * @vmname: the name of the VM * @vmuuid: the UUID of the VM * @privileged: whether we are running in privileged mode * @swtpm_user: The userid to switch to when setting up the TPM; * typically this should be the uid of 'tss' or 'root' * @swtpm_group: The group id to switch to * @logfile: The file to write the log into; it must be writable * for the user given by userid or 'tss' * @tpmversion: The version of the TPM, either a TPM 1.2 or TPM 2 * * Setup the external swtpm by creating endorsement key and * certificates for it. */ static int qemuTPMEmulatorRunSetup(const char *storagepath, const char *vmname, const unsigned char *vmuuid, bool privileged, uid_t swtpm_user, gid_t swtpm_group, const char *logfile, const virDomainTPMVersion tpmversion) { virCommandPtr cmd = NULL; int exitstatus; int ret = -1; char uuid[VIR_UUID_STRING_BUFLEN]; char *vmid = NULL; if (!privileged && tpmversion == VIR_DOMAIN_TPM_VERSION_1_2) return virFileWriteStr(logfile, _("Did not create EK and certificates since " "this requires privileged mode for a " "TPM 1.2\n"), 0600); cmd = virCommandNew(swtpm_setup); if (!cmd) goto cleanup; virUUIDFormat(vmuuid, uuid); if (virAsprintf(&vmid, "%s:%s", vmname, uuid) < 0) goto cleanup; virCommandSetUID(cmd, swtpm_user); virCommandSetGID(cmd, swtpm_group); switch (tpmversion) { case VIR_DOMAIN_TPM_VERSION_1_2: break; case VIR_DOMAIN_TPM_VERSION_2_0: virCommandAddArgList(cmd, "--tpm2", NULL); break; case VIR_DOMAIN_TPM_VERSION_DEFAULT: case VIR_DOMAIN_TPM_VERSION_LAST: break; } virCommandAddArgList(cmd, "--tpm-state", storagepath, "--vmid", vmid, "--logfile", logfile, "--createek", "--create-ek-cert", "--create-platform-cert", "--lock-nvram", "--not-overwrite", NULL); virCommandClearCaps(cmd); if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not run '%s'. exitstatus: %d; " "Check error log '%s' for details."), swtpm_setup, exitstatus, logfile); goto cleanup; } ret = 0; cleanup: VIR_FREE(vmid); virCommandFree(cmd); return ret; }