Commit 92b7e492 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'tpmdd-next-v5.9' of git://git.infradead.org/users/jjs/linux-tpmdd

Pull tpm updates from Jarkko Sakkinen:
 "An issue was fixed with the TPM space buffer size. The buffer is used
  to store in-TPM objects while swapped out of the TPM for a /dev/tpmrm0
  session. The code incorrectly used PAGE_SIZE, which obviously can
  vary. With these changes the buffer has a fixed size of 16 kB.

  In addition, this contains support for acquiring TPM even log from
  TPM2 ACPI table. This method is used by QEMU in particular"

* tag 'tpmdd-next-v5.9' of git://git.infradead.org/users/jjs/linux-tpmdd:
  tpm: Add support for event log pointer found in TPM2 ACPI table
  acpi: Extend TPM2 ACPI table with missing log fields
  tpm: Unify the mismatching TPM space buffer sizes
  tpm: Require that all digests are present in TCG_PCR_EVENT2 structures
parents c6fe44d9 85467f63
Loading
Loading
Loading
Loading
+42 −21
Original line number Diff line number Diff line
@@ -49,9 +49,9 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
	void __iomem *virt;
	u64 len, start;
	struct tpm_bios_log *log;

	if (chip->flags & TPM_CHIP_FLAG_TPM2)
		return -ENODEV;
	struct acpi_table_tpm2 *tbl;
	struct acpi_tpm2_phy *tpm2_phy;
	int format;

	log = &chip->log;

@@ -61,10 +61,28 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
	if (!chip->acpi_dev_handle)
		return -ENODEV;

	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
		status = acpi_get_table("TPM2", 1,
					(struct acpi_table_header **)&tbl);
		if (ACPI_FAILURE(status))
			return -ENODEV;

		if (tbl->header.length <
				sizeof(*tbl) + sizeof(struct acpi_tpm2_phy))
			return -ENODEV;

		tpm2_phy = (void *)tbl + sizeof(*tbl);
		len = tpm2_phy->log_area_minimum_length;

		start = tpm2_phy->log_area_start_address;
		if (!start || !len)
			return -ENODEV;

		format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
	} else {
		/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
		status = acpi_get_table(ACPI_SIG_TCPA, 1,
					(struct acpi_table_header **)&buff);

		if (ACPI_FAILURE(status))
			return -ENODEV;

@@ -79,6 +97,9 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
			start = buff->client.log_start_addr;
			break;
		}

		format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
	}
	if (!len) {
		dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
		return -EIO;
@@ -98,7 +119,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
	memcpy_fromio(log->bios_event_log, virt, len);

	acpi_os_unmap_iomem(virt, len);
	return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
	return format;

err:
	kfree(log->bios_event_log);
+2 −7
Original line number Diff line number Diff line
@@ -386,13 +386,8 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
	chip->cdev.owner = THIS_MODULE;
	chip->cdevs.owner = THIS_MODULE;

	chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
	if (!chip->work_space.context_buf) {
		rc = -ENOMEM;
		goto out;
	}
	chip->work_space.session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
	if (!chip->work_space.session_buf) {
	rc = tpm2_init_space(&chip->work_space, TPM2_SPACE_BUFFER_SIZE);
	if (rc) {
		rc = -ENOMEM;
		goto out;
	}
+4 −1
Original line number Diff line number Diff line
@@ -59,6 +59,9 @@ enum tpm_addr {

#define TPM_TAG_RQU_COMMAND 193

/* TPM2 specific constants. */
#define TPM2_SPACE_BUFFER_SIZE		16384 /* 16 kB */

struct	stclear_flags_t {
	__be16	tag;
	u8	deactivated;
@@ -228,7 +231,7 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm2_probe(struct tpm_chip *chip);
int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip);
int tpm2_find_cc(struct tpm_chip *chip, u32 cc);
int tpm2_init_space(struct tpm_space *space);
int tpm2_init_space(struct tpm_space *space, unsigned int buf_size);
void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space);
void tpm2_flush_space(struct tpm_chip *chip);
int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
+16 −10
Original line number Diff line number Diff line
@@ -38,18 +38,21 @@ static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space)
	}
}

int tpm2_init_space(struct tpm_space *space)
int tpm2_init_space(struct tpm_space *space, unsigned int buf_size)
{
	space->context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
	space->context_buf = kzalloc(buf_size, GFP_KERNEL);
	if (!space->context_buf)
		return -ENOMEM;

	space->session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
	space->session_buf = kzalloc(buf_size, GFP_KERNEL);
	if (space->session_buf == NULL) {
		kfree(space->context_buf);
		/* Prevent caller getting a dangling pointer. */
		space->context_buf = NULL;
		return -ENOMEM;
	}

	space->buf_size = buf_size;
	return 0;
}

@@ -311,8 +314,10 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
	       sizeof(space->context_tbl));
	memcpy(&chip->work_space.session_tbl, &space->session_tbl,
	       sizeof(space->session_tbl));
	memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE);
	memcpy(chip->work_space.session_buf, space->session_buf, PAGE_SIZE);
	memcpy(chip->work_space.context_buf, space->context_buf,
	       space->buf_size);
	memcpy(chip->work_space.session_buf, space->session_buf,
	       space->buf_size);

	rc = tpm2_load_space(chip);
	if (rc) {
@@ -492,7 +497,7 @@ static int tpm2_save_space(struct tpm_chip *chip)
			continue;

		rc = tpm2_save_context(chip, space->context_tbl[i],
				       space->context_buf, PAGE_SIZE,
				       space->context_buf, space->buf_size,
				       &offset);
		if (rc == -ENOENT) {
			space->context_tbl[i] = 0;
@@ -509,9 +514,8 @@ static int tpm2_save_space(struct tpm_chip *chip)
			continue;

		rc = tpm2_save_context(chip, space->session_tbl[i],
				       space->session_buf, PAGE_SIZE,
				       space->session_buf, space->buf_size,
				       &offset);

		if (rc == -ENOENT) {
			/* handle error saving session, just forget it */
			space->session_tbl[i] = 0;
@@ -557,8 +561,10 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
	       sizeof(space->context_tbl));
	memcpy(&space->session_tbl, &chip->work_space.session_tbl,
	       sizeof(space->session_tbl));
	memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE);
	memcpy(space->session_buf, chip->work_space.session_buf, PAGE_SIZE);
	memcpy(space->context_buf, chip->work_space.context_buf,
	       space->buf_size);
	memcpy(space->session_buf, chip->work_space.session_buf,
	       space->buf_size);

	return 0;
out:
+1 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ static int tpmrm_open(struct inode *inode, struct file *file)
	if (priv == NULL)
		return -ENOMEM;

	rc = tpm2_init_space(&priv->space);
	rc = tpm2_init_space(&priv->space, TPM2_SPACE_BUFFER_SIZE);
	if (rc) {
		kfree(priv);
		return -ENOMEM;
Loading