mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 05:26:07 +00:00
Hi Linus,
This the trimmed down version of the previous pull request. BR, Jarkko -----BEGIN PGP SIGNATURE----- iIgEABYIADAWIQRE6pSOnaBC00OEHEIaerohdGur0gUCZLW0JxIcamFya2tvQGtl cm5lbC5vcmcACgkQGnq6IXRrq9JawQEAihoRREYBYq+SjsQgn75Nj1PAsqP4FSAy 7/Oy4s54j/MA/0j6bcyfC8rqUk/m2o4A1ssNJ2dnEYYV6Z5sKXNpDDoI =qhda -----END PGP SIGNATURE----- Merge tag 'tpmdd-v6.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd Pull tpm fixes from Jarkko Sakkinen. Mostly interrupt storm fixes, with some other minor changes. * tag 'tpmdd-v6.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd: tpm,tpm_tis: Disable interrupts after 1000 unhandled IRQs tpm/tpm_tis: Disable interrupts for Lenovo L590 devices tpm: Do not remap from ACPI resources again for Pluton TPM tpm/tpm_tis: Disable interrupts for Framework Laptop Intel 13th gen tpm/tpm_tis: Disable interrupts for Framework Laptop Intel 12th gen security: keys: Modify mismatched function name tpm: return false from tpm_amd_is_rng_defective on non-x86 platforms keys: Fix linking a duplicate key to a keyring's assoc_array tpm: tis_i2c: Limit write bursts to I2C_SMBUS_BLOCK_MAX (32) bytes tpm: tis_i2c: Limit read bursts to I2C_SMBUS_BLOCK_MAX (32) bytes tpm_tis_spi: Release chip select when flow control fails tpm: tpm_tis: Disable interrupts *only* for AEON UPX-i11 tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
This commit is contained in:
commit
f2f393c385
@ -518,6 +518,7 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip)
|
||||
* 6.x.y.z series: 6.0.18.6 +
|
||||
* 3.x.y.z series: 3.57.y.5 +
|
||||
*/
|
||||
#ifdef CONFIG_X86
|
||||
static bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
|
||||
{
|
||||
u32 val1, val2;
|
||||
@ -566,6 +567,12 @@ release:
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static inline bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_X86 */
|
||||
|
||||
static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
|
||||
{
|
||||
|
@ -563,15 +563,18 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
|
||||
u32 rsp_size;
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&acpi_resource_list);
|
||||
ret = acpi_dev_get_resources(device, &acpi_resource_list,
|
||||
crb_check_resource, iores_array);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
acpi_dev_free_resource_list(&acpi_resource_list);
|
||||
|
||||
/* Pluton doesn't appear to define ACPI memory regions */
|
||||
/*
|
||||
* Pluton sometimes does not define ACPI memory regions.
|
||||
* Mapping is then done in crb_map_pluton
|
||||
*/
|
||||
if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) {
|
||||
INIT_LIST_HEAD(&acpi_resource_list);
|
||||
ret = acpi_dev_get_resources(device, &acpi_resource_list,
|
||||
crb_check_resource, iores_array);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
acpi_dev_free_resource_list(&acpi_resource_list);
|
||||
|
||||
if (resource_type(iores_array) != IORESOURCE_MEM) {
|
||||
dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n");
|
||||
return -EINVAL;
|
||||
|
@ -114,6 +114,22 @@ static int tpm_tis_disable_irq(const struct dmi_system_id *d)
|
||||
}
|
||||
|
||||
static const struct dmi_system_id tpm_tis_dmi_table[] = {
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "Framework Laptop (12th Gen Intel Core)",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (12th Gen Intel Core)"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "Framework Laptop (13th Gen Intel Core)",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (13th Gen Intel Core)"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "ThinkPad T490s",
|
||||
@ -138,11 +154,20 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L490"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "ThinkPad L590",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L590"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "UPX-TGL",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "UPX-TGL"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
|
@ -24,9 +24,12 @@
|
||||
#include <linux/wait.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/dmi.h>
|
||||
#include "tpm.h"
|
||||
#include "tpm_tis_core.h"
|
||||
|
||||
#define TPM_TIS_MAX_UNHANDLED_IRQS 1000
|
||||
|
||||
static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value);
|
||||
|
||||
static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
|
||||
@ -468,25 +471,29 @@ out_err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void disable_interrupts(struct tpm_chip *chip)
|
||||
static void __tpm_tis_disable_interrupts(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
u32 int_mask = 0;
|
||||
|
||||
tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &int_mask);
|
||||
int_mask &= ~TPM_GLOBAL_INT_ENABLE;
|
||||
tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), int_mask);
|
||||
|
||||
chip->flags &= ~TPM_CHIP_FLAG_IRQ;
|
||||
}
|
||||
|
||||
static void tpm_tis_disable_interrupts(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
u32 intmask;
|
||||
int rc;
|
||||
|
||||
if (priv->irq == 0)
|
||||
return;
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
|
||||
if (rc < 0)
|
||||
intmask = 0;
|
||||
|
||||
intmask &= ~TPM_GLOBAL_INT_ENABLE;
|
||||
rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
|
||||
__tpm_tis_disable_interrupts(chip);
|
||||
|
||||
devm_free_irq(chip->dev.parent, priv->irq, chip);
|
||||
priv->irq = 0;
|
||||
chip->flags &= ~TPM_CHIP_FLAG_IRQ;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -552,7 +559,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
|
||||
if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
|
||||
tpm_msleep(1);
|
||||
if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
|
||||
disable_interrupts(chip);
|
||||
tpm_tis_disable_interrupts(chip);
|
||||
set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
|
||||
return rc;
|
||||
}
|
||||
@ -752,6 +759,57 @@ static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
|
||||
return status == TPM_STS_COMMAND_READY;
|
||||
}
|
||||
|
||||
static irqreturn_t tpm_tis_revert_interrupts(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
const char *product;
|
||||
const char *vendor;
|
||||
|
||||
dev_warn(&chip->dev, FW_BUG
|
||||
"TPM interrupt storm detected, polling instead\n");
|
||||
|
||||
vendor = dmi_get_system_info(DMI_SYS_VENDOR);
|
||||
product = dmi_get_system_info(DMI_PRODUCT_VERSION);
|
||||
|
||||
if (vendor && product) {
|
||||
dev_info(&chip->dev,
|
||||
"Consider adding the following entry to tpm_tis_dmi_table:\n");
|
||||
dev_info(&chip->dev, "\tDMI_SYS_VENDOR: %s\n", vendor);
|
||||
dev_info(&chip->dev, "\tDMI_PRODUCT_VERSION: %s\n", product);
|
||||
}
|
||||
|
||||
if (tpm_tis_request_locality(chip, 0) != 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
__tpm_tis_disable_interrupts(chip);
|
||||
tpm_tis_relinquish_locality(chip, 0);
|
||||
|
||||
schedule_work(&priv->free_irq_work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t tpm_tis_update_unhandled_irqs(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
irqreturn_t irqret = IRQ_HANDLED;
|
||||
|
||||
if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (time_after(jiffies, priv->last_unhandled_irq + HZ/10))
|
||||
priv->unhandled_irqs = 1;
|
||||
else
|
||||
priv->unhandled_irqs++;
|
||||
|
||||
priv->last_unhandled_irq = jiffies;
|
||||
|
||||
if (priv->unhandled_irqs > TPM_TIS_MAX_UNHANDLED_IRQS)
|
||||
irqret = tpm_tis_revert_interrupts(chip);
|
||||
|
||||
return irqret;
|
||||
}
|
||||
|
||||
static irqreturn_t tis_int_handler(int dummy, void *dev_id)
|
||||
{
|
||||
struct tpm_chip *chip = dev_id;
|
||||
@ -761,10 +819,10 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt);
|
||||
if (rc < 0)
|
||||
return IRQ_NONE;
|
||||
goto err;
|
||||
|
||||
if (interrupt == 0)
|
||||
return IRQ_NONE;
|
||||
goto err;
|
||||
|
||||
set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
|
||||
if (interrupt & TPM_INTF_DATA_AVAIL_INT)
|
||||
@ -780,10 +838,13 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
|
||||
rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt);
|
||||
tpm_tis_relinquish_locality(chip, 0);
|
||||
if (rc < 0)
|
||||
return IRQ_NONE;
|
||||
goto err;
|
||||
|
||||
tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
err:
|
||||
return tpm_tis_update_unhandled_irqs(chip);
|
||||
}
|
||||
|
||||
static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
|
||||
@ -804,6 +865,15 @@ static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
|
||||
chip->flags &= ~TPM_CHIP_FLAG_IRQ;
|
||||
}
|
||||
|
||||
static void tpm_tis_free_irq_func(struct work_struct *work)
|
||||
{
|
||||
struct tpm_tis_data *priv = container_of(work, typeof(*priv), free_irq_work);
|
||||
struct tpm_chip *chip = priv->chip;
|
||||
|
||||
devm_free_irq(chip->dev.parent, priv->irq, chip);
|
||||
priv->irq = 0;
|
||||
}
|
||||
|
||||
/* Register the IRQ and issue a command that will cause an interrupt. If an
|
||||
* irq is seen then leave the chip setup for IRQ operation, otherwise reverse
|
||||
* everything and leave in polling mode. Returns 0 on success.
|
||||
@ -816,6 +886,7 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
|
||||
int rc;
|
||||
u32 int_status;
|
||||
|
||||
INIT_WORK(&priv->free_irq_work, tpm_tis_free_irq_func);
|
||||
|
||||
rc = devm_request_threaded_irq(chip->dev.parent, irq, NULL,
|
||||
tis_int_handler, IRQF_ONESHOT | flags,
|
||||
@ -918,6 +989,7 @@ void tpm_tis_remove(struct tpm_chip *chip)
|
||||
interrupt = 0;
|
||||
|
||||
tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt);
|
||||
flush_work(&priv->free_irq_work);
|
||||
|
||||
tpm_tis_clkrun_enable(chip, false);
|
||||
|
||||
@ -1021,6 +1093,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
||||
chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX);
|
||||
chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX);
|
||||
chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX);
|
||||
priv->chip = chip;
|
||||
priv->timeout_min = TPM_TIMEOUT_USECS_MIN;
|
||||
priv->timeout_max = TPM_TIMEOUT_USECS_MAX;
|
||||
priv->phy_ops = phy_ops;
|
||||
@ -1179,7 +1252,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
||||
rc = tpm_tis_request_locality(chip, 0);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
disable_interrupts(chip);
|
||||
tpm_tis_disable_interrupts(chip);
|
||||
tpm_tis_relinquish_locality(chip, 0);
|
||||
}
|
||||
}
|
||||
|
@ -91,11 +91,15 @@ enum tpm_tis_flags {
|
||||
};
|
||||
|
||||
struct tpm_tis_data {
|
||||
struct tpm_chip *chip;
|
||||
u16 manufacturer_id;
|
||||
struct mutex locality_count_mutex;
|
||||
unsigned int locality_count;
|
||||
int locality;
|
||||
int irq;
|
||||
struct work_struct free_irq_work;
|
||||
unsigned long last_unhandled_irq;
|
||||
unsigned int unhandled_irqs;
|
||||
unsigned int int_mask;
|
||||
unsigned long flags;
|
||||
void __iomem *ilb_base_addr;
|
||||
|
@ -189,21 +189,28 @@ static int tpm_tis_i2c_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < TPM_RETRY; i++) {
|
||||
/* write register */
|
||||
msg.len = sizeof(reg);
|
||||
msg.buf = ®
|
||||
msg.flags = 0;
|
||||
ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
u16 read = 0;
|
||||
|
||||
/* read data */
|
||||
msg.buf = result;
|
||||
msg.len = len;
|
||||
msg.flags = I2C_M_RD;
|
||||
ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
while (read < len) {
|
||||
/* write register */
|
||||
msg.len = sizeof(reg);
|
||||
msg.buf = ®
|
||||
msg.flags = 0;
|
||||
ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* read data */
|
||||
msg.buf = result + read;
|
||||
msg.len = len - read;
|
||||
msg.flags = I2C_M_RD;
|
||||
if (msg.len > I2C_SMBUS_BLOCK_MAX)
|
||||
msg.len = I2C_SMBUS_BLOCK_MAX;
|
||||
ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
read += msg.len;
|
||||
}
|
||||
|
||||
ret = tpm_tis_i2c_sanity_check_read(reg, len, result);
|
||||
if (ret == 0)
|
||||
@ -223,19 +230,27 @@ static int tpm_tis_i2c_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
|
||||
struct i2c_msg msg = { .addr = phy->i2c_client->addr };
|
||||
u8 reg = tpm_tis_i2c_address_to_register(addr);
|
||||
int ret;
|
||||
u16 wrote = 0;
|
||||
|
||||
if (len > TPM_BUFSIZE - 1)
|
||||
return -EIO;
|
||||
|
||||
/* write register and data in one go */
|
||||
phy->io_buf[0] = reg;
|
||||
memcpy(phy->io_buf + sizeof(reg), value, len);
|
||||
|
||||
msg.len = sizeof(reg) + len;
|
||||
msg.buf = phy->io_buf;
|
||||
ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
while (wrote < len) {
|
||||
/* write register and data in one go */
|
||||
msg.len = sizeof(reg) + len - wrote;
|
||||
if (msg.len > I2C_SMBUS_BLOCK_MAX)
|
||||
msg.len = I2C_SMBUS_BLOCK_MAX;
|
||||
|
||||
memcpy(phy->io_buf + sizeof(reg), value + wrote,
|
||||
msg.len - sizeof(reg));
|
||||
|
||||
ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
wrote += msg.len - sizeof(reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -136,6 +136,14 @@ int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
|
||||
}
|
||||
|
||||
exit:
|
||||
if (ret < 0) {
|
||||
/* Deactivate chip select */
|
||||
memset(&spi_xfer, 0, sizeof(spi_xfer));
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&spi_xfer, &m);
|
||||
spi_sync_locked(phy->spi_device, &m);
|
||||
}
|
||||
|
||||
spi_bus_unlock(phy->spi_device->master);
|
||||
return ret;
|
||||
}
|
||||
|
@ -683,37 +683,21 @@ static struct miscdevice vtpmx_miscdev = {
|
||||
.fops = &vtpmx_fops,
|
||||
};
|
||||
|
||||
static int vtpmx_init(void)
|
||||
{
|
||||
return misc_register(&vtpmx_miscdev);
|
||||
}
|
||||
|
||||
static void vtpmx_cleanup(void)
|
||||
{
|
||||
misc_deregister(&vtpmx_miscdev);
|
||||
}
|
||||
|
||||
static int __init vtpm_module_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = vtpmx_init();
|
||||
if (rc) {
|
||||
pr_err("couldn't create vtpmx device\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
workqueue = create_workqueue("tpm-vtpm");
|
||||
if (!workqueue) {
|
||||
pr_err("couldn't create workqueue\n");
|
||||
rc = -ENOMEM;
|
||||
goto err_vtpmx_cleanup;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_vtpmx_cleanup:
|
||||
vtpmx_cleanup();
|
||||
rc = misc_register(&vtpmx_miscdev);
|
||||
if (rc) {
|
||||
pr_err("couldn't create vtpmx device\n");
|
||||
destroy_workqueue(workqueue);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -721,7 +705,7 @@ err_vtpmx_cleanup:
|
||||
static void __exit vtpm_module_exit(void)
|
||||
{
|
||||
destroy_workqueue(workqueue);
|
||||
vtpmx_cleanup();
|
||||
misc_deregister(&vtpmx_miscdev);
|
||||
}
|
||||
|
||||
module_init(vtpm_module_init);
|
||||
|
@ -401,17 +401,21 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
|
||||
set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
|
||||
|
||||
if (dest_keyring) {
|
||||
ret = __key_link_lock(dest_keyring, &ctx->index_key);
|
||||
ret = __key_link_lock(dest_keyring, &key->index_key);
|
||||
if (ret < 0)
|
||||
goto link_lock_failed;
|
||||
ret = __key_link_begin(dest_keyring, &ctx->index_key, &edit);
|
||||
if (ret < 0)
|
||||
goto link_prealloc_failed;
|
||||
}
|
||||
|
||||
/* attach the key to the destination keyring under lock, but we do need
|
||||
/*
|
||||
* Attach the key to the destination keyring under lock, but we do need
|
||||
* to do another check just in case someone beat us to it whilst we
|
||||
* waited for locks */
|
||||
* waited for locks.
|
||||
*
|
||||
* The caller might specify a comparison function which looks for keys
|
||||
* that do not exactly match but are still equivalent from the caller's
|
||||
* perspective. The __key_link_begin() operation must be done only after
|
||||
* an actual key is determined.
|
||||
*/
|
||||
mutex_lock(&key_construction_mutex);
|
||||
|
||||
rcu_read_lock();
|
||||
@ -420,12 +424,16 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
|
||||
if (!IS_ERR(key_ref))
|
||||
goto key_already_present;
|
||||
|
||||
if (dest_keyring)
|
||||
if (dest_keyring) {
|
||||
ret = __key_link_begin(dest_keyring, &key->index_key, &edit);
|
||||
if (ret < 0)
|
||||
goto link_alloc_failed;
|
||||
__key_link(dest_keyring, key, &edit);
|
||||
}
|
||||
|
||||
mutex_unlock(&key_construction_mutex);
|
||||
if (dest_keyring)
|
||||
__key_link_end(dest_keyring, &ctx->index_key, edit);
|
||||
__key_link_end(dest_keyring, &key->index_key, edit);
|
||||
mutex_unlock(&user->cons_lock);
|
||||
*_key = key;
|
||||
kleave(" = 0 [%d]", key_serial(key));
|
||||
@ -438,10 +446,13 @@ key_already_present:
|
||||
mutex_unlock(&key_construction_mutex);
|
||||
key = key_ref_to_ptr(key_ref);
|
||||
if (dest_keyring) {
|
||||
ret = __key_link_begin(dest_keyring, &key->index_key, &edit);
|
||||
if (ret < 0)
|
||||
goto link_alloc_failed_unlocked;
|
||||
ret = __key_link_check_live_key(dest_keyring, key);
|
||||
if (ret == 0)
|
||||
__key_link(dest_keyring, key, &edit);
|
||||
__key_link_end(dest_keyring, &ctx->index_key, edit);
|
||||
__key_link_end(dest_keyring, &key->index_key, edit);
|
||||
if (ret < 0)
|
||||
goto link_check_failed;
|
||||
}
|
||||
@ -456,8 +467,10 @@ link_check_failed:
|
||||
kleave(" = %d [linkcheck]", ret);
|
||||
return ret;
|
||||
|
||||
link_prealloc_failed:
|
||||
__key_link_end(dest_keyring, &ctx->index_key, edit);
|
||||
link_alloc_failed:
|
||||
mutex_unlock(&key_construction_mutex);
|
||||
link_alloc_failed_unlocked:
|
||||
__key_link_end(dest_keyring, &key->index_key, edit);
|
||||
link_lock_failed:
|
||||
mutex_unlock(&user->cons_lock);
|
||||
key_put(key);
|
||||
|
@ -186,7 +186,7 @@ int tpm2_key_priv(void *context, size_t hdrlen,
|
||||
}
|
||||
|
||||
/**
|
||||
* tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
|
||||
* tpm2_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
|
||||
*
|
||||
* @buf: an allocated tpm_buf instance
|
||||
* @session_handle: session handle
|
||||
|
Loading…
x
Reference in New Issue
Block a user