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>
---
include/libvirt/virterror.h | 2 +
src/libvirt_private.syms | 2 +
src/util/virerror.c | 2 +
src/util/virtpm.c | 136 +++++++++++++++++++++++++++++++++++-
src/util/virtpm.h | 15 ++++
5 files changed, 155 insertions(+), 2 deletions(-)
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 102a2573bf..6f4110185a 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -134,6 +134,8 @@ typedef enum {
VIR_FROM_FIREWALLD = 68, /* Error from firewalld */
VIR_FROM_DOMAIN_CHECKPOINT = 69, /* Error from domain checkpoint */
+ VIR_FROM_TPM = 70, /* Error from TPM */
+
# ifdef VIR_ENUM_SENTINELS
VIR_ERR_DOMAIN_LAST
# endif
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4cdbb80596..cf80ea3e44 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/virerror.c b/src/util/virerror.c
index dfba8c5712..77f76a9abf 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -142,6 +142,8 @@ VIR_ENUM_IMPL(virErrorDomain,
"Resource control",
"FirewallD",
"Domain Checkpoint",
+
+ "TPM", /* 70 */
);
diff --git a/src/util/virtpm.c b/src/util/virtpm.c
index bef6cff3dd..99abbf3f8b 100644
--- a/src/util/virtpm.c
+++ b/src/util/virtpm.c
@@ -27,8 +27,24 @@
#include "viralloc.h"
#include "virfile.h"
#include "virtpm.h"
+#include "vircommand.h"
+#include "virbitmap.h"
+#include "virjson.h"
+#include "virlog.h"
-#define VIR_FROM_THIS VIR_FROM_NONE
+#define VIR_FROM_THIS VIR_FROM_TPM
+
+VIR_LOG_INIT("util.tpm");
+
+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:
@@ -74,18 +90,23 @@ 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 virMutex swtpm_tools_lock = VIR_MUTEX_INITIALIZER;
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 *);
+
char *
virTPMGetSwtpm(void)
{
@@ -131,6 +152,101 @@ virTPMGetSwtpmIoctl(void)
return s;
}
+/* 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) {
+ VIR_DEBUG("Found swtpm that doesn't support
--print-capabilities");
+ return bitmap;
+ }
+
+ 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;
+}
+
+static virBitmapPtr
+virTPMGetCaps(TypeFromStringFn typeFromStringFn,
+ const char *exec, const char *param1)
+{
+ VIR_AUTOPTR(virCommand) cmd = NULL;
+
+ if (!(cmd = virCommandNew(exec)))
+ return NULL;
+
+ if (param1)
+ virCommandAddArg(cmd, param1);
+ virCommandAddArg(cmd, "--print-capabilities");
+ virCommandClearCaps(cmd);
+
+ return virTPMExecGetCaps(cmd, typeFromStringFn);
+}
+
/*
* virTPMEmulatorInit
*
@@ -145,16 +261,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",
@@ -209,6 +333,14 @@ virTPMEmulatorInit(void)
goto cleanup;
}
*prgs[i].path = path;
+
+ if (prgs[i].caps) {
+ *prgs[i].caps = virTPMGetCaps(prgs[i].typeFromStringFn,
+ path, prgs[i].parm);
+ path = NULL;
+ if (!*prgs[i].caps)
+ goto cleanup;
+ }
path = NULL;
}
}
diff --git a/src/util/virtpm.h b/src/util/virtpm.h
index 2311f04ae5..157b43ff17 100644
--- a/src/util/virtpm.h
+++ b/src/util/virtpm.h
@@ -26,3 +26,18 @@ char *virTPMGetSwtpm(void);
char *virTPMGetSwtpmSetup(void);
char *virTPMGetSwtpmIoctl(void);
int virTPMEmulatorInit(void);
+
+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);
--
2.20.1