Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4d8c7c9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull security subsystem fixes from James Morris:
 "This includes several fixes for TPM, as well as a fix for the x.509
  certificate parser to address CVE-2015-5327"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  X.509: Fix the time validation [ver #2]
  tpm: fix compat 'ppi' link handling in tpm_chip_register()
  tpm: fix missing migratable flag in sealing functionality for TPM2
  TPM: revert the list handling logic fixed in 398a1e71
  TPM: Avoid reference to potentially freed memory
  tpm_tis: restore IRQ vector in IO memory after failed probing
  tpm_tis: free irq after probing
parents a18e2fa5 cc25b994
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -531,7 +531,11 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
	if (*p != 'Z')
		goto unsupported_time;

	mon_len = month_lengths[mon];
	if (year < 1970 ||
	    mon < 1 || mon > 12)
		goto invalid_time;

	mon_len = month_lengths[mon - 1];
	if (mon == 2) {
		if (year % 4 == 0) {
			mon_len = 29;
@@ -543,9 +547,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
		}
	}

	if (year < 1970 ||
	    mon < 1 || mon > 12 ||
	    day < 1 || day > mon_len ||
	if (day < 1 || day > mon_len ||
	    hour > 23 ||
	    min > 59 ||
	    sec > 59)
+11 −9
Original line number Diff line number Diff line
@@ -226,21 +226,23 @@ int tpm_chip_register(struct tpm_chip *chip)
	if (rc)
		goto out_err;

	if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
		rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj,
							    &chip->dev.kobj,
							    "ppi");
		if (rc)
			goto out_err;
	}

	/* Make the chip available. */
	spin_lock(&driver_lock);
	list_add_rcu(&chip->list, &tpm_chip_list);
	list_add_tail_rcu(&chip->list, &tpm_chip_list);
	spin_unlock(&driver_lock);

	chip->flags |= TPM_CHIP_FLAG_REGISTERED;

	if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
		rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj,
							    &chip->dev.kobj,
							    "ppi");
		if (rc && rc != -ENOENT) {
			tpm_chip_unregister(chip);
			return rc;
		}
	}

	return 0;
out_err:
	tpm1_chip_unregister(chip);
+10 −5
Original line number Diff line number Diff line
@@ -443,12 +443,13 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
			     TPM_DIGEST_SIZE);

	/* sensitive */
	tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len);
	tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len + 1);

	tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE);
	tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE);
	tpm_buf_append_u16(&buf, payload->key_len);
	tpm_buf_append_u16(&buf, payload->key_len + 1);
	tpm_buf_append(&buf, payload->key, payload->key_len);
	tpm_buf_append_u8(&buf, payload->migratable);

	/* public */
	tpm_buf_append_u16(&buf, 14);
@@ -573,6 +574,8 @@ static int tpm2_unseal(struct tpm_chip *chip,
		       u32 blob_handle)
{
	struct tpm_buf buf;
	u16 data_len;
	u8 *data;
	int rc;

	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
@@ -591,11 +594,13 @@ static int tpm2_unseal(struct tpm_chip *chip,
		rc = -EPERM;

	if (!rc) {
		payload->key_len = be16_to_cpup(
		data_len = be16_to_cpup(
			(__be16 *) &buf.data[TPM_HEADER_SIZE + 4]);
		data = &buf.data[TPM_HEADER_SIZE + 6];

		memcpy(payload->key, &buf.data[TPM_HEADER_SIZE + 6],
		       payload->key_len);
		memcpy(payload->key, data, data_len - 1);
		payload->key_len = data_len - 1;
		payload->migratable = data[data_len - 1];
	}

	tpm_buf_destroy(&buf);
+2 −1
Original line number Diff line number Diff line
@@ -53,17 +53,18 @@ int read_log(struct tpm_bios_log *log)
		goto cleanup_eio;
	}

	of_node_put(np);
	log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
	if (!log->bios_event_log) {
		pr_err("%s: ERROR - Not enough memory for BIOS measurements\n",
		       __func__);
		of_node_put(np);
		return -ENOMEM;
	}

	log->bios_event_log_end = log->bios_event_log + *sizep;

	memcpy(log->bios_event_log, __va(*basep), *sizep);
	of_node_put(np);

	return 0;

+7 −1
Original line number Diff line number Diff line
@@ -645,6 +645,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
{
	u32 vendor, intfcaps, intmask;
	int rc, i, irq_s, irq_e, probe;
	int irq_r = -1;
	struct tpm_chip *chip;
	struct priv_data *priv;

@@ -751,6 +752,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
		irq_s =
		    ioread8(chip->vendor.iobase +
			    TPM_INT_VECTOR(chip->vendor.locality));
		irq_r = irq_s;
		if (irq_s) {
			irq_e = irq_s;
		} else {
@@ -805,6 +807,8 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
			iowrite32(intmask,
				  chip->vendor.iobase +
				  TPM_INT_ENABLE(chip->vendor.locality));

			devm_free_irq(dev, i, chip);
		}
	}
	if (chip->vendor.irq) {
@@ -831,7 +835,9 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
				  chip->vendor.iobase +
				  TPM_INT_ENABLE(chip->vendor.locality));
		}
	}
	} else if (irq_r != -1)
		iowrite8(irq_r, chip->vendor.iobase +
			 TPM_INT_VECTOR(chip->vendor.locality));

	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
		chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);