[libvirt] [PATCH v2 3/3] qemu: Pass file descriptor when using TPM passthrough
Stefan Berger
stefanb at linux.vnet.ibm.com
Fri Mar 6 01:07:58 UTC 2015
On 03/05/2015 10:25 AM, Michal Privoznik wrote:
> On 03.03.2015 15:40, Stefan Berger wrote:
>> 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 at linux.vnet.ibm.com>
>> ---
>> src/qemu/qemu_command.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 117 insertions(+), 4 deletions(-)
>>
>> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
>> index d6bc294..4c6b76d 100644
>> --- a/src/qemu/qemu_command.c
>> +++ b/src/qemu/qemu_command.c
>> @@ -161,6 +161,58 @@ VIR_ENUM_IMPL(qemuNumaPolicy, VIR_DOMAIN_NUMATUNE_MEM_LAST,
>> "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)
>> * @driver: pointer to the driver instance
>> @@ -6321,15 +6373,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) {
>> @@ -6341,11 +6398,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;
>> + }
> I'm thinking of how to test this code, but those open() complicate the
> things. Unless we want to mock them in qemuxml2argvmock.c which would
> not be trivial after all.
>
> ACK series.
>
> Michal
>
Pushed
Stefan
More information about the libvir-list
mailing list