[libvirt] [PATCH v5 04/11] Helper functions for host TPM support
Daniel P. Berrange
berrange at redhat.com
Fri Apr 12 10:24:44 UTC 2013
On Thu, Apr 11, 2013 at 04:04:46PM -0400, Stefan Berger wrote:
> Implement helper functions to find the TPM's sysfs cancel file.
>
> Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
> Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
> Tested-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
>
> ---
> po/POTFILES.in | 1
> src/Makefile.am | 1
> src/libvirt_private.syms | 4 +
> src/util/virtpm.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++
> src/util/virtpm.h | 27 +++++++++
> 5 files changed, 165 insertions(+)
>
> Index: libvirt/src/Makefile.am
> ===================================================================
> --- libvirt.orig/src/Makefile.am
> +++ libvirt/src/Makefile.am
> @@ -122,6 +122,7 @@ UTIL_SOURCES = \
> util/virthreadwin32.h \
> util/virthreadpool.c util/virthreadpool.h \
> util/virtime.h util/virtime.c \
> + util/virtpm.h util/virtpm.c \
> util/virtypedparam.c util/virtypedparam.h \
> util/virusb.c util/virusb.h \
> util/viruri.h util/viruri.c \
> Index: libvirt/src/util/virtpm.c
> ===================================================================
> --- /dev/null
> +++ libvirt/src/util/virtpm.c
> @@ -0,0 +1,132 @@
> +/*
> + * virtpm.c: TPM support
> + *
> + * Copyright (C) 2013 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/>.
> + *
> + * Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
> + */
> +
> +#include <config.h>
> +
> +#include <stdio.h>
> +#include <dirent.h>
> +#include <unistd.h>
> +#include <sys/stat.h>
> +
> +#include "c-ctype.h"
> +#include "virobject.h"
> +#include "viralloc.h"
> +#include "virutil.h"
> +#include "virerror.h"
> +#include "virbuffer.h"
> +#include "virtpm.h"
> +
> +#define VIR_FROM_THIS VIR_FROM_NONE
> +
> +/*
> + * Check whether the given base path, e.g., /sys/class/misc/tpm0/device,
> + * is the sysfs entry of a TPM. A TPM sysfs entry should be uniquely
> + * recognizable by the file entries 'pcrs' and 'cancel'.
> + * Upon success the basepath with '/cancel' appended is returned, NULL
> + * otherwise.
> + */
> +static char *
> +virTPMCheckSysfsCancel(char *basepath)
> +{
> + char *path = NULL;
> + struct stat statbuf;
> +
> + if (virAsprintf(&path, "%s/pcrs", basepath) < 0) {
> + virReportOOMError();
> + goto cleanup;
> + }
> +
> + if (stat(path, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Could not determine TPM cancel path since pcrs "
> + "file was not found in directory %s"),
> + basepath);
> + goto cleanup;
> + }
> +
> + VIR_FREE(path);
> +
> + if (virAsprintf(&path, "%s/cancel", basepath) < 0) {
> + virReportOOMError();
> + goto cleanup;
> + }
> +
> + if (stat(path, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Could not determine TPM cancel path since cancel "
> + "file was not found in directory %s"),
> + basepath);
> + goto cleanup;
> + }
> +
> + return path;
> +
> +cleanup:
> + VIR_FREE(path);
> + return NULL;
> +}
> +
> +
> +char *
> +virTPMFindCancelPath(void)
> +{
> + unsigned int idx;
> + DIR *pnp_dir;
> + char *path = NULL, *basepath = NULL;
> + struct dirent *entry;
> +
> + pnp_dir = opendir("/sys/class/misc");
> + if (pnp_dir != NULL) {
> + while ((entry = readdir(pnp_dir)) != NULL) {
> + /* expecting 'tpm%u' -- skip other file patterns */
> + if (!STRPREFIX(entry->d_name, "tpm") ||
> + virStrToLong_ui(entry->d_name + strlen("tpm"),
> + NULL, 10, &idx) < 0)
> + continue;
> + if (virAsprintf(&basepath, "/sys/class/misc/%s/device",
> + entry->d_name) < 0) {
> + virReportOOMError();
> + break;
> + }
> + if ((path = virTPMCheckSysfsCancel(basepath)))
> + break;
> +
> + VIR_FREE(basepath);
> + }
> + closedir(pnp_dir);
> + } else {
> + virReportSystemError(errno, "%s",
> + _("Could not open directory /sys/class/misc "
> + "to find TPM cancel path"));
> + }
> +
> + VIR_FREE(basepath);
> +
> + /* report error if no path was found & no error was reported earlier */
> + if (!path && !virGetLastError())
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + "%s",
> + _("Could not determine TPM cancel path. You may need "
> + "to insert the TPM driver module into the kernel"));
> +
> + return path;
> +}
Hmm, actually on second thoughts the entirely approach for this
method is just flawed.
In the XML description you have:
<device path='/dev/tpm0'/>
So we should not be iterating over /sys/fs/misc/tpmNNN at all.
We know exactly which TPM device we want - it is 'tpm0'. Just
kill all this pointless readdir code & pass in the device name
we want to get the cancel path for.
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list