mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 09:17:52 +03:00
qemu: Pass file descriptor when using TPM passthrough
Pass the TPM file descriptor to QEMU via command line. Instead of passing /dev/tpm0 we now pass /dev/fdset/10 and the additional parameters -add-fd set=10,fd=20. This addresses the use case when QEMU is started with non-root privileges and QEMU cannot open /dev/tpm0 for example. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
parent
42bee147fe
commit
9954a8bfc2
@ -160,6 +160,58 @@ VIR_ENUM_IMPL(qemuNumaPolicy, VIR_DOMAIN_NUMATUNE_MEM_LAST,
|
||||
"preferred",
|
||||
"interleave");
|
||||
|
||||
/**
|
||||
* qemuVirCommandGetFDSet:
|
||||
* @cmd: the command to modify
|
||||
* @fd: fd to reassign to the child
|
||||
*
|
||||
* Get the parameters for the QEMU -add-fd command line option
|
||||
* for the given file descriptor. The file descriptor must previously
|
||||
* have been 'transferred' in a virCommandPassFD() call.
|
||||
* This function for example returns "set=10,fd=20".
|
||||
*/
|
||||
static char *
|
||||
qemuVirCommandGetFDSet(virCommandPtr cmd, int fd)
|
||||
{
|
||||
char *result = NULL;
|
||||
int idx = virCommandPassFDGetFDIndex(cmd, fd);
|
||||
|
||||
if (idx >= 0) {
|
||||
ignore_value(virAsprintf(&result, "set=%d,fd=%d", idx, fd));
|
||||
} else {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("file descriptor %d has not been transferred"), fd);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* qemuVirCommandGetDevSet:
|
||||
* @cmd: the command to modify
|
||||
* @fd: fd to reassign to the child
|
||||
*
|
||||
* Get the parameters for the QEMU path= parameter where a file
|
||||
* descriptor is accessed via a file descriptor set, for example
|
||||
* /dev/fdset/10. The file descriptor must previously have been
|
||||
* 'transferred' in a virCommandPassFD() call.
|
||||
*/
|
||||
static char *
|
||||
qemuVirCommandGetDevSet(virCommandPtr cmd, int fd)
|
||||
{
|
||||
char *result = NULL;
|
||||
int idx = virCommandPassFDGetFDIndex(cmd, fd);
|
||||
|
||||
if (idx >= 0) {
|
||||
ignore_value(virAsprintf(&result, "/dev/fdset/%d", idx));
|
||||
} else {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("file descriptor %d has not been transferred"), fd);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* qemuPhysIfaceConnect:
|
||||
* @def: the definition of the VM (needed by 802.1Qbh and audit)
|
||||
@ -6322,15 +6374,20 @@ qemuBuildRNGDevStr(virDomainDefPtr def,
|
||||
|
||||
|
||||
static char *qemuBuildTPMBackendStr(const virDomainDef *def,
|
||||
virCommandPtr cmd,
|
||||
virQEMUCapsPtr qemuCaps,
|
||||
const char *emulator)
|
||||
const char *emulator,
|
||||
int *tpmfd, int *cancelfd)
|
||||
{
|
||||
const virDomainTPMDef *tpm = def->tpm;
|
||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||
const char *type = virDomainTPMBackendTypeToString(tpm->type);
|
||||
char *cancel_path;
|
||||
char *cancel_path = NULL, *devset = NULL;
|
||||
const char *tpmdev;
|
||||
|
||||
*tpmfd = -1;
|
||||
*cancelfd = -1;
|
||||
|
||||
virBufferAsprintf(&buf, "%s,id=tpm-%s", type, tpm->info.alias);
|
||||
|
||||
switch (tpm->type) {
|
||||
@ -6342,11 +6399,42 @@ static char *qemuBuildTPMBackendStr(const virDomainDef *def,
|
||||
if (!(cancel_path = virTPMCreateCancelPath(tpmdev)))
|
||||
goto error;
|
||||
|
||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_ADD_FD)) {
|
||||
*tpmfd = open(tpmdev, O_RDWR);
|
||||
if (*tpmfd < 0) {
|
||||
virReportSystemError(errno, _("Could not open TPM device %s"),
|
||||
tpmdev);
|
||||
goto error;
|
||||
}
|
||||
|
||||
virCommandPassFD(cmd, *tpmfd,
|
||||
VIR_COMMAND_PASS_FD_CLOSE_PARENT);
|
||||
devset = qemuVirCommandGetDevSet(cmd, *tpmfd);
|
||||
if (devset == NULL)
|
||||
goto error;
|
||||
|
||||
*cancelfd = open(cancel_path, O_WRONLY);
|
||||
if (*cancelfd < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Could not open TPM device's cancel "
|
||||
"path %s"), cancel_path);
|
||||
goto error;
|
||||
}
|
||||
VIR_FREE(cancel_path);
|
||||
|
||||
virCommandPassFD(cmd, *cancelfd,
|
||||
VIR_COMMAND_PASS_FD_CLOSE_PARENT);
|
||||
cancel_path = qemuVirCommandGetDevSet(cmd, *cancelfd);
|
||||
if (cancel_path == NULL)
|
||||
goto error;
|
||||
}
|
||||
virBufferAddLit(&buf, ",path=");
|
||||
virBufferEscape(&buf, ',', ",", "%s", tpmdev);
|
||||
virBufferEscape(&buf, ',', ",", "%s", devset ? devset : tpmdev);
|
||||
|
||||
virBufferAddLit(&buf, ",cancel-path=");
|
||||
virBufferEscape(&buf, ',', ",", "%s", cancel_path);
|
||||
|
||||
VIR_FREE(devset);
|
||||
VIR_FREE(cancel_path);
|
||||
|
||||
break;
|
||||
@ -6366,6 +6454,9 @@ static char *qemuBuildTPMBackendStr(const virDomainDef *def,
|
||||
emulator, type);
|
||||
|
||||
error:
|
||||
VIR_FREE(devset);
|
||||
VIR_FREE(cancel_path);
|
||||
|
||||
virBufferFreeAndReset(&buf);
|
||||
return NULL;
|
||||
}
|
||||
@ -8199,13 +8290,35 @@ qemuBuildTPMCommandLine(virDomainDefPtr def,
|
||||
const char *emulator)
|
||||
{
|
||||
char *optstr;
|
||||
int tpmfd = -1;
|
||||
int cancelfd = -1;
|
||||
char *fdset;
|
||||
|
||||
if (!(optstr = qemuBuildTPMBackendStr(def, qemuCaps, emulator)))
|
||||
if (!(optstr = qemuBuildTPMBackendStr(def, cmd, qemuCaps, emulator,
|
||||
&tpmfd, &cancelfd)))
|
||||
return -1;
|
||||
|
||||
virCommandAddArgList(cmd, "-tpmdev", optstr, NULL);
|
||||
VIR_FREE(optstr);
|
||||
|
||||
if (tpmfd >= 0) {
|
||||
fdset = qemuVirCommandGetFDSet(cmd, tpmfd);
|
||||
if (!fdset)
|
||||
return -1;
|
||||
|
||||
virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
|
||||
VIR_FREE(fdset);
|
||||
}
|
||||
|
||||
if (cancelfd >= 0) {
|
||||
fdset = qemuVirCommandGetFDSet(cmd, cancelfd);
|
||||
if (!fdset)
|
||||
return -1;
|
||||
|
||||
virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
|
||||
VIR_FREE(fdset);
|
||||
}
|
||||
|
||||
if (!(optstr = qemuBuildTPMDevStr(def, qemuCaps, emulator)))
|
||||
return -1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user