Implement helper functions to find the TPM's sysfs cancel file. Signed-off-by: Stefan Berger Reviewed-by: Corey Bryant Tested-by: Corey Bryant --- 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 + * . + * + * Author: Stefan Berger + */ + +#include + +#include +#include +#include +#include + +#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; +} Index: libvirt/src/libvirt_private.syms =================================================================== --- libvirt.orig/src/libvirt_private.syms +++ libvirt/src/libvirt_private.syms @@ -1781,6 +1781,10 @@ virTimeStringThen; virTimeStringThenRaw; +# util/virtpm.h +virTPMFindCancelPath; + + # util/virtypedparam.h virTypedParameterArrayValidate; virTypedParameterAssign; Index: libvirt/src/util/virtpm.h =================================================================== --- /dev/null +++ libvirt/src/util/virtpm.h @@ -0,0 +1,27 @@ +/* + * virtpm.h: 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 + * . + * + * Author: Stefan Berger + */ +#ifndef __VIR_TPM_H__ +# define __VIR_TPM_H__ + +char *virTPMFindCancelPath(void); + +#endif /* __VIR_TPM_H__ */ Index: libvirt/po/POTFILES.in =================================================================== --- libvirt.orig/po/POTFILES.in +++ libvirt/po/POTFILES.in @@ -181,6 +181,7 @@ src/util/virsysinfo.c src/util/virerror.c src/util/virerror.h src/util/virtime.c +src/util/virtpm.c src/util/virtypedparam.c src/util/viruri.c src/util/virusb.c