On Tue, Jul 9, 2019 at 9:24 PM Stefan Berger <stefanb@xxxxxxxxxxxxxxxxxx> wrote: > > Run 'swtpm socket --print-capabilities' and > 'swtpm_setup --print-capabilities' to get the JSON object of the > features the programs are supporting and parse them into a bitmap. > > Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxx> > --- > src/conf/Makefile.inc.am | 6 ++ > src/conf/virtpm_conf.c | 36 ++++++++++++ > src/conf/virtpm_conf.h | 36 ++++++++++++ > src/libvirt_private.syms | 5 ++ > src/tpm/Makefile.inc.am | 5 +- > src/tpm/virtpm.c | 123 ++++++++++++++++++++++++++++++++++++++- > 6 files changed, 209 insertions(+), 2 deletions(-) > create mode 100644 src/conf/virtpm_conf.c > create mode 100644 src/conf/virtpm_conf.h > > diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am > index 08c7c9da7f..e42425fcc5 100644 > --- a/src/conf/Makefile.inc.am > +++ b/src/conf/Makefile.inc.am > @@ -153,6 +153,11 @@ DEVICE_CONF_SOURCES = \ > conf/device_conf.h \ > $(NULL) > > +TPM_CONF_SOURCES = \ > + conf/virtpm_conf.c \ > + conf/virtpm_conf.h \ > + $(NULL) > + > CONF_SOURCES = \ > $(NETDEV_CONF_SOURCES) \ > $(DOMAIN_CONF_SOURCES) \ > @@ -171,6 +176,7 @@ CONF_SOURCES = \ > $(CPU_CONF_SOURCES) \ > $(CHRDEV_CONF_SOURCES) \ > $(DEVICE_CONF_SOURCES) \ > + $(TPM_CONF_SOURCES) \ > $(NULL) > > noinst_LTLIBRARIES += libvirt_conf.la > diff --git a/src/conf/virtpm_conf.c b/src/conf/virtpm_conf.c > new file mode 100644 > index 0000000000..12e69e67b3 > --- /dev/null > +++ b/src/conf/virtpm_conf.c > @@ -0,0 +1,36 @@ > +/* > + * virtpm_conf.c: vTPM XML processing > + * > + * Copyright (C) 2019 IBM Corporation > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library. If not, see > + * <http://www.gnu.org/licenses/>. > + */ > + > +#include <config.h> > + > +#include "virenum.h" > +#include "virtpm_conf.h" > + > +#define VIR_FROM_THIS VIR_FROM_NONE > + > +VIR_ENUM_IMPL(virTPMSwtpmFeature, > + VIR_TPM_SWTPM_FEATURE_LAST, > + "cmdarg-pwd-fd", > +); > + > +VIR_ENUM_IMPL(virTPMSwtpmSetupFeature, > + VIR_TPM_SWTPM_SETUP_FEATURE_LAST, > + "cmdarg-pwdfile-fd", > +); > diff --git a/src/conf/virtpm_conf.h b/src/conf/virtpm_conf.h > new file mode 100644 > index 0000000000..73c6c67271 > --- /dev/null > +++ b/src/conf/virtpm_conf.h > @@ -0,0 +1,36 @@ > +/* > + * virtpm_conf.h: vTPM XML processing > + * > + * Copyright (C) 2019 IBM Corporation > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library. If not, see > + * <http://www.gnu.org/licenses/>. > + */ > + > +#pragma once > + > +typedef enum { > + VIR_TPM_SWTPM_FEATURE_CMDARG_PWD_FD, > + > + VIR_TPM_SWTPM_FEATURE_LAST > +} virTPMSwtpmFeature; > + > +typedef enum { > + VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_PWDFILE_FD, > + > + VIR_TPM_SWTPM_SETUP_FEATURE_LAST > +} virTPMSwtpmSetupFeature; > + > +VIR_ENUM_DECL(virTPMSwtpmFeature); > +VIR_ENUM_DECL(virTPMSwtpmSetupFeature); > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index e33d7d9f14..d2045895a1 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1236,6 +1236,11 @@ virStoragePoolObjVolumeGetNames; > virStoragePoolObjVolumeListExport; > > > +# conf/virtpm_conf.h > +virTPMSwtpmFeatureTypeFromString; > +virTPMSwtpmSetupFeatureTypeFromString; > + > + > # cpu/cpu.h > cpuDecode; > cpuEncode; > diff --git a/src/tpm/Makefile.inc.am b/src/tpm/Makefile.inc.am > index 1f5131bf34..d8a15c406c 100644 > --- a/src/tpm/Makefile.inc.am > +++ b/src/tpm/Makefile.inc.am > @@ -12,6 +12,9 @@ EXTRA_DIST += \ > > noinst_LTLIBRARIES += libvirt_tpm.la > libvirt_la_BUILT_LIBADD += libvirt_tpm.la > -libvirt_tpm_la_CFLAGS = $(AM_CFLAGS) > +libvirt_tpm_la_CFLAGS = \ > + -I$(srcdir)/conf \ > + $(AM_CFLAGS) \ > + $(NULL) > libvirt_tpm_la_LDFLAGS = $(AM_LDFLAGS) > libvirt_tpm_la_SOURCES = $(TPM_UTIL_SOURCES) > diff --git a/src/tpm/virtpm.c b/src/tpm/virtpm.c > index e4735f9c4d..42dd2b1bb2 100644 > --- a/src/tpm/virtpm.c > +++ b/src/tpm/virtpm.c > @@ -27,6 +27,10 @@ > #include "viralloc.h" > #include "virfile.h" > #include "virtpm.h" > +#include "vircommand.h" > +#include "virbitmap.h" > +#include "virjson.h" > +#include "virtpm_conf.h" > > #define VIR_FROM_THIS VIR_FROM_NONE > > @@ -74,17 +78,22 @@ virTPMCreateCancelPath(const char *devpath) > } > > /* > - * executables for the swtpm; to be found on the host > + * executables for the swtpm; to be found on the host along with > + * capabilties bitmap > */ > static char *swtpm_path; > static struct stat swtpm_stat; > +static virBitmapPtr swtpm_caps; > > static char *swtpm_setup; > static struct stat swtpm_setup_stat; > +static virBitmapPtr swtpm_setup_caps; > > static char *swtpm_ioctl; > static struct stat swtpm_ioctl_stat; > > +typedef int (*TypeFromStringFn)(const char *); > + > const char * > virTPMGetSwtpm(void) > { > @@ -109,6 +118,106 @@ virTPMGetSwtpmIoctl(void) > return swtpm_ioctl; > } > > +/* virTPMExecGetCaps > + * > + * Execute the prepared command and parse the returned JSON object > + * to get the capabilities supported by the executable. > + * A JSON object like this is expected: > + * > + * { > + * "type": "swtpm", > + * "features": [ > + * "cmdarg-seccomp", > + * "cmdarg-key-fd", > + * "cmdarg-pwd-fd" > + * ] > + * } > + */ > +static virBitmapPtr > +virTPMExecGetCaps(virCommandPtr cmd, > + TypeFromStringFn typeFromStringFn) > +{ > + int exitstatus; > + virBitmapPtr bitmap; > + char *outbuf = NULL; > + virJSONValuePtr json = NULL; > + virJSONValuePtr featureList; > + virJSONValuePtr item; > + size_t idx; > + const char *str; > + int typ; > + > + if (!(bitmap = virBitmapNewEmpty())) > + return NULL; > + > + virCommandSetOutputBuffer(cmd, &outbuf); > + /* We allow the command to fail since older versions of it may > + * not support --print-capabilities > + */ > + if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) > + goto cleanup; We should probably fail if the command failed to run, and skip if exitstatus != 0. > + > + json = virJSONValueFromString(outbuf); > + if (!json) > + goto error_bad_json; > + > + featureList = virJSONValueObjectGetArray(json, "features"); > + if (!featureList) > + goto error_bad_json; > + > + if (!virJSONValueIsArray(featureList)) > + goto error_bad_json; > + > + for (idx = 0; idx < virJSONValueArraySize(featureList); idx++) { > + item = virJSONValueArrayGet(featureList, idx); > + if (!item) > + continue; > + > + str = virJSONValueGetString(item); > + if (!str) > + goto error_bad_json; > + typ = typeFromStringFn(str); > + if (typ < 0) > + continue; > + > + if (virBitmapSetBitExpand(bitmap, typ) < 0) > + goto cleanup; > + } > + > + cleanup: > + VIR_FREE(outbuf); > + virJSONValueFree(json); Please use VIR_AUTOFREE and VIR_AUTOPTR > + > + return bitmap; > + > + error_bad_json: > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Unexpected JSON format: %s"), outbuf); > + goto cleanup; > +} > + > +static virBitmapPtr > +virTPMGetCaps(TypeFromStringFn typeFromStringFn, > + const char *exec, const char *param1) > +{ > + virCommandPtr cmd; > + virBitmapPtr bitmap; > + > + cmd = virCommandNew(exec); > + if (!cmd) > + return NULL; > + if (param1) > + virCommandAddArg(cmd, param1); Hmm, I would expect --print-capabilites to be top-level argument, not a sub-command argument. > + virCommandAddArg(cmd, "--print-capabilities"); > + virCommandClearCaps(cmd); > + > + bitmap = virTPMExecGetCaps(cmd, typeFromStringFn); > + > + virCommandFree(cmd); > + > + return bitmap; > +} > + > /* > * virTPMEmulatorInit > * > @@ -122,16 +231,24 @@ virTPMEmulatorInit(void) > const char *name; > char **path; > struct stat *stat; > + const char *parm; > + virBitmapPtr *caps; > + TypeFromStringFn typeFromStringFn; > } prgs[] = { > { > .name = "swtpm", > .path = &swtpm_path, > .stat = &swtpm_stat, > + .parm = "socket", > + .caps = &swtpm_caps, > + .typeFromStringFn = virTPMSwtpmFeatureTypeFromString, > }, > { > .name = "swtpm_setup", > .path = &swtpm_setup, > .stat = &swtpm_setup_stat, > + .caps = &swtpm_setup_caps, > + .typeFromStringFn = virTPMSwtpmSetupFeatureTypeFromString, > }, > { > .name = "swtpm_ioctl", > @@ -186,6 +303,10 @@ virTPMEmulatorInit(void) > tmp = *prgs[i].path; > *prgs[i].path = path; > VIR_FREE(tmp); > + > + if (prgs[i].caps) > + *prgs[i].caps = virTPMGetCaps(prgs[i].typeFromStringFn, > + path, prgs[i].parm); > } > } > > -- > 2.20.1 > other than that, looks good -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list