tpm: Simplify creation of cancel path

Simplify the creation of the cancel path given the TPM's device path.
Given the path /dev/tpm0 build the path /sys/class/misc/tpm0/device/cancel.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-id: 1366146516-23814-1-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Stefan Berger 2013-04-16 17:08:36 -04:00 committed by Anthony Liguori
parent 56863d4f19
commit 8e36d6ca34
1 changed files with 17 additions and 57 deletions

View File

@ -351,46 +351,18 @@ static int tpm_passthrough_test_tpmdev(int fd)
return 0;
}
/*
* Check whether the given base path, e.g., /sys/class/misc/tpm0/device,
* is the sysfs directory of a TPM. A TPM sysfs directory should be uniquely
* recognizable by the file entries 'pcrs' and 'cancel'.
* Upon success 'true' is returned and the basebath buffer has '/cancel'
* appended.
*/
static bool tpm_passthrough_check_sysfs_cancel(char *basepath, size_t bufsz)
{
char path[PATH_MAX];
struct stat statbuf;
snprintf(path, sizeof(path), "%s/pcrs", basepath);
if (stat(path, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
return false;
}
snprintf(path, sizeof(path), "%s/cancel", basepath);
if (stat(path, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
return false;
}
strncpy(basepath, path, bufsz);
return true;
}
/*
* Unless path or file descriptor set has been provided by user,
* determine the sysfs cancel file following kernel documentation
* in Documentation/ABI/stable/sysfs-class-tpm.
* From /dev/tpm0 create /sys/class/misc/tpm0/device/cancel
*/
static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
int fd = -1;
unsigned int idx;
DIR *pnp_dir;
char *dev;
char path[PATH_MAX];
struct dirent entry, *result;
int len;
if (tb->cancel_path) {
fd = qemu_open(tb->cancel_path, O_WRONLY);
@ -401,34 +373,22 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
return fd;
}
snprintf(path, sizeof(path), "/sys/class/misc");
pnp_dir = opendir(path);
if (pnp_dir != NULL) {
while (readdir_r(pnp_dir, &entry, &result) == 0 &&
result != NULL) {
/*
* only allow /sys/class/misc/tpm%u type of paths
*/
if (sscanf(entry.d_name, "tpm%u%n", &idx, &len) < 1 ||
len <= strlen("tpm") ||
len != strlen(entry.d_name)) {
continue;
}
snprintf(path, sizeof(path), "/sys/class/misc/%s/device",
entry.d_name);
if (!tpm_passthrough_check_sysfs_cancel(path, sizeof(path))) {
continue;
}
dev = strrchr(tpm_pt->tpm_dev, '/');
if (dev) {
dev++;
if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/cancel",
dev) < sizeof(path)) {
fd = qemu_open(path, O_WRONLY);
break;
if (fd >= 0) {
tb->cancel_path = g_strdup(path);
} else {
error_report("tpm_passthrough: Could not open TPM cancel "
"path %s : %s", path, strerror(errno));
}
}
closedir(pnp_dir);
}
if (fd >= 0) {
tb->cancel_path = g_strdup(path);
} else {
error_report("tpm_passthrough: Bad TPM device path %s",
tpm_pt->tpm_dev);
}
return fd;