
On Fri, Jul 12, 2019 at 12:23:44PM -0400, Stefan Berger 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@linux.ibm.com> --- src/libvirt_private.syms | 2 + src/util/virtpm.c | 134 +++++++++++++++++++++++++++++++++++++-- src/util/virtpm.h | 15 +++++ 3 files changed, 147 insertions(+), 4 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5b3c176862..5200adae3f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3181,6 +3181,8 @@ virTPMEmulatorInit; virTPMGetSwtpm; virTPMGetSwtpmIoctl; virTPMGetSwtpmSetup; +virTPMSwtpmFeatureTypeFromString; +virTPMSwtpmSetupFeatureTypeFromString;
# util/virtypedparam.h diff --git a/src/util/virtpm.c b/src/util/virtpm.c index e4735f9c4d..692033e899 100644 --- a/src/util/virtpm.c +++ b/src/util/virtpm.c @@ -27,9 +27,22 @@ #include "viralloc.h" #include "virfile.h" #include "virtpm.h" +#include "vircommand.h" +#include "virbitmap.h" +#include "virjson.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", +); + /** * virTPMCreateCancelPath: * @devpath: Path to the TPM device @@ -74,17 +87,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 +127,99 @@ 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; + VIR_AUTOFREE(char *) outbuf = NULL; + VIR_AUTOPTR(virJSONValue) json = NULL; + virJSONValuePtr featureList; + virJSONValuePtr item; + size_t idx; + const char *str; + int typ; + + virCommandSetOutputBuffer(cmd, &outbuf); + if (virCommandRun(cmd, &exitstatus) < 0) + return NULL; + + if (!(bitmap = virBitmapNewEmpty())) + return NULL; + + /* older version does not support --print-capabilties -- that's fine */ + if (exitstatus != 0) + return bitmap;
We can't distinguish from an old version that lacks --print-capabilties and from a new version that crashed when running --print-capabilties. The latter shouldn't happen in general, but I thin kwe ought to at least put a VIR_DEBUG in here to make it obvious we're treating this as if we hit an old binary when looking at logs.
+ + 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: + return bitmap; + + error_bad_json: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected JSON format: %s"), outbuf); + goto cleanup; +}
@@ -142,7 +261,7 @@ virTPMEmulatorInit(void) size_t i;
for (i = 0; i < ARRAY_CARDINALITY(prgs); i++) { - char *path; + VIR_AUTOFREE(char *) path = NULL; bool findit = *prgs[i].path == NULL; struct stat statbuf; char *tmp; @@ -174,18 +293,25 @@ virTPMEmulatorInit(void) virReportError(VIR_ERR_INTERNAL_ERROR, _("%s is not an executable"), path); - VIR_FREE(path); return -1; } if (stat(path, prgs[i].stat) < 0) { virReportSystemError(errno, _("Could not stat %s"), path); - VIR_FREE(path); return -1; }
If you re-post this series, just use VIR_AUTOFREE straightaway in the earlier patch. With the debug line added Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|