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(a)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(a)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 :|