tpmdd fixes for Linux v5.5-rc3
-----BEGIN PGP SIGNATURE----- iJYEABYIAD4WIQRE6pSOnaBC00OEHEIaerohdGur0gUCXfrLASAcamFya2tvLnNh a2tpbmVuQGxpbnV4LmludGVsLmNvbQAKCRAaerohdGur0pZfAQD9F5Vjdqp3fWk+ pxt+eD9+xaD2MYuSVO2AEVBC949vdQD/TP7xnb66w7n9YtMtm9MgvysHAakJYeAe l4XsHAiPHgI= =CFIs -----END PGP SIGNATURE----- Merge tag 'tpmdd-next-20191219' of git://git.infradead.org/users/jjs/linux-tpmdd Pull tpm fixes from Jarkko Sakkinen: "Bunch of fixes for rc3" * tag 'tpmdd-next-20191219' of git://git.infradead.org/users/jjs/linux-tpmdd: tpm/tpm_ftpm_tee: add shutdown call back tpm: selftest: cleanup after unseal with wrong auth/policy test tpm: selftest: add test covering async mode tpm: fix invalid locking in NONBLOCKING mode security: keys: trusted: fix lost handle flush tpm_tis: reserve chip for duration of tpm_tis_core_init KEYS: asymmetric: return ENOMEM if akcipher_request_alloc() fails KEYS: remove CONFIG_KEYS_COMPAT
This commit is contained in:
commit
4a94c43323
|
@ -470,6 +470,7 @@ static int tpm_key_encrypt(struct tpm_key *tk,
|
|||
if (ret < 0)
|
||||
goto error_free_tfm;
|
||||
|
||||
ret = -ENOMEM;
|
||||
req = akcipher_request_alloc(tfm, GFP_KERNEL);
|
||||
if (!req)
|
||||
goto error_free_tfm;
|
||||
|
|
|
@ -184,6 +184,7 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
|
|||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
|
||||
ret = -ENOMEM;
|
||||
req = akcipher_request_alloc(tfm, GFP_KERNEL);
|
||||
if (!req)
|
||||
goto error_free_tfm;
|
||||
|
|
|
@ -61,6 +61,12 @@ static void tpm_dev_async_work(struct work_struct *work)
|
|||
|
||||
mutex_lock(&priv->buffer_mutex);
|
||||
priv->command_enqueued = false;
|
||||
ret = tpm_try_get_ops(priv->chip);
|
||||
if (ret) {
|
||||
priv->response_length = ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
|
||||
sizeof(priv->data_buffer));
|
||||
tpm_put_ops(priv->chip);
|
||||
|
@ -68,6 +74,7 @@ static void tpm_dev_async_work(struct work_struct *work)
|
|||
priv->response_length = ret;
|
||||
mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&priv->buffer_mutex);
|
||||
wake_up_interruptible(&priv->async_wait);
|
||||
}
|
||||
|
@ -204,6 +211,7 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
|
|||
if (file->f_flags & O_NONBLOCK) {
|
||||
priv->command_enqueued = true;
|
||||
queue_work(tpm_dev_wq, &priv->async_work);
|
||||
tpm_put_ops(priv->chip);
|
||||
mutex_unlock(&priv->buffer_mutex);
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -218,7 +218,6 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
|
|||
int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
|
||||
struct tpm_digest *digests);
|
||||
int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max);
|
||||
void tpm2_flush_context(struct tpm_chip *chip, u32 handle);
|
||||
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
|
||||
u32 *value, const char *desc);
|
||||
|
||||
|
|
|
@ -362,6 +362,7 @@ void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
|
|||
tpm_transmit_cmd(chip, &buf, 0, "flushing context");
|
||||
tpm_buf_destroy(&buf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm2_flush_context);
|
||||
|
||||
struct tpm2_get_cap_out {
|
||||
u8 more_data;
|
||||
|
|
|
@ -32,7 +32,7 @@ static const uuid_t ftpm_ta_uuid =
|
|||
0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96);
|
||||
|
||||
/**
|
||||
* ftpm_tee_tpm_op_recv - retrieve fTPM response.
|
||||
* ftpm_tee_tpm_op_recv() - retrieve fTPM response.
|
||||
* @chip: the tpm_chip description as specified in driver/char/tpm/tpm.h.
|
||||
* @buf: the buffer to store data.
|
||||
* @count: the number of bytes to read.
|
||||
|
@ -61,7 +61,7 @@ static int ftpm_tee_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
|||
}
|
||||
|
||||
/**
|
||||
* ftpm_tee_tpm_op_send - send TPM commands through the TEE shared memory.
|
||||
* ftpm_tee_tpm_op_send() - send TPM commands through the TEE shared memory.
|
||||
* @chip: the tpm_chip description as specified in driver/char/tpm/tpm.h
|
||||
* @buf: the buffer to send.
|
||||
* @len: the number of bytes to send.
|
||||
|
@ -208,7 +208,7 @@ static int ftpm_tee_match(struct tee_ioctl_version_data *ver, const void *data)
|
|||
}
|
||||
|
||||
/**
|
||||
* ftpm_tee_probe - initialize the fTPM
|
||||
* ftpm_tee_probe() - initialize the fTPM
|
||||
* @pdev: the platform_device description.
|
||||
*
|
||||
* Return:
|
||||
|
@ -298,7 +298,7 @@ out_tee_session:
|
|||
}
|
||||
|
||||
/**
|
||||
* ftpm_tee_remove - remove the TPM device
|
||||
* ftpm_tee_remove() - remove the TPM device
|
||||
* @pdev: the platform_device description.
|
||||
*
|
||||
* Return:
|
||||
|
@ -328,6 +328,19 @@ static int ftpm_tee_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ftpm_tee_shutdown() - shutdown the TPM device
|
||||
* @pdev: the platform_device description.
|
||||
*/
|
||||
static void ftpm_tee_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct ftpm_tee_private *pvt_data = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
tee_shm_free(pvt_data->shm);
|
||||
tee_client_close_session(pvt_data->ctx, pvt_data->session);
|
||||
tee_client_close_context(pvt_data->ctx);
|
||||
}
|
||||
|
||||
static const struct of_device_id of_ftpm_tee_ids[] = {
|
||||
{ .compatible = "microsoft,ftpm" },
|
||||
{ }
|
||||
|
@ -341,6 +354,7 @@ static struct platform_driver ftpm_tee_driver = {
|
|||
},
|
||||
.probe = ftpm_tee_probe,
|
||||
.remove = ftpm_tee_remove,
|
||||
.shutdown = ftpm_tee_shutdown,
|
||||
};
|
||||
|
||||
module_platform_driver(ftpm_tee_driver);
|
||||
|
|
|
@ -978,13 +978,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
|||
|
||||
if (wait_startup(chip, 0) != 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
goto err_start;
|
||||
}
|
||||
|
||||
/* Take control of the TPM's interrupt hardware and shut it off */
|
||||
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
goto err_start;
|
||||
|
||||
intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
|
||||
TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
|
||||
|
@ -993,21 +993,21 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
|||
|
||||
rc = tpm_chip_start(chip);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
goto err_start;
|
||||
|
||||
rc = tpm2_probe(chip);
|
||||
tpm_chip_stop(chip);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
|
||||
priv->manufacturer_id = vendor;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_RID(0), &rid);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
|
||||
dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
|
||||
(chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
|
||||
|
@ -1016,13 +1016,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
|||
probe = probe_itpm(chip);
|
||||
if (probe < 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
/* Figure out the capabilities */
|
||||
rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
|
||||
dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
|
||||
intfcaps);
|
||||
|
@ -1056,10 +1056,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
|||
if (tpm_get_timeouts(chip)) {
|
||||
dev_err(dev, "Could not get TPM timeouts and durations\n");
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
tpm_chip_start(chip);
|
||||
chip->flags |= TPM_CHIP_FLAG_IRQ;
|
||||
if (irq) {
|
||||
tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
|
||||
|
@ -1070,18 +1069,20 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
|||
} else {
|
||||
tpm_tis_probe_irq(chip, intmask);
|
||||
}
|
||||
tpm_chip_stop(chip);
|
||||
}
|
||||
|
||||
tpm_chip_stop(chip);
|
||||
|
||||
rc = tpm_chip_register(chip);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
if (chip->ops->clk_enable != NULL)
|
||||
chip->ops->clk_enable(chip, false);
|
||||
goto err_start;
|
||||
|
||||
return 0;
|
||||
out_err:
|
||||
|
||||
err_probe:
|
||||
tpm_chip_stop(chip);
|
||||
|
||||
err_start:
|
||||
if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL))
|
||||
chip->ops->clk_enable(chip, false);
|
||||
|
||||
|
|
|
@ -403,6 +403,7 @@ extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
|
|||
extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen);
|
||||
extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);
|
||||
extern struct tpm_chip *tpm_default_chip(void);
|
||||
void tpm2_flush_context(struct tpm_chip *chip, u32 handle);
|
||||
#else
|
||||
static inline int tpm_is_tpm2(struct tpm_chip *chip)
|
||||
{
|
||||
|
|
|
@ -21,10 +21,6 @@ config KEYS
|
|||
|
||||
If you are unsure as to whether this is required, answer N.
|
||||
|
||||
config KEYS_COMPAT
|
||||
def_bool y
|
||||
depends on COMPAT && KEYS
|
||||
|
||||
config KEYS_REQUEST_CACHE
|
||||
bool "Enable temporary caching of the last request_key() result"
|
||||
depends on KEYS
|
||||
|
|
|
@ -17,7 +17,7 @@ obj-y := \
|
|||
request_key_auth.o \
|
||||
user_defined.o
|
||||
compat-obj-$(CONFIG_KEY_DH_OPERATIONS) += compat_dh.o
|
||||
obj-$(CONFIG_KEYS_COMPAT) += compat.o $(compat-obj-y)
|
||||
obj-$(CONFIG_COMPAT) += compat.o $(compat-obj-y)
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
obj-$(CONFIG_SYSCTL) += sysctl.o
|
||||
obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o
|
||||
|
|
|
@ -46,11 +46,6 @@ static long compat_keyctl_instantiate_key_iov(
|
|||
|
||||
/*
|
||||
* The key control system call, 32-bit compatibility version for 64-bit archs
|
||||
*
|
||||
* This should only be called if the 64-bit arch uses weird pointers in 32-bit
|
||||
* mode or doesn't guarantee that the top 32-bits of the argument registers on
|
||||
* taking a 32-bit syscall are zero. If you can, you should call sys_keyctl()
|
||||
* directly.
|
||||
*/
|
||||
COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
|
||||
u32, arg2, u32, arg3, u32, arg4, u32, arg5)
|
||||
|
|
|
@ -264,7 +264,7 @@ extern long keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *,
|
|||
size_t, struct keyctl_kdf_params __user *);
|
||||
extern long __keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *,
|
||||
size_t, struct keyctl_kdf_params *);
|
||||
#ifdef CONFIG_KEYS_COMPAT
|
||||
#ifdef CONFIG_COMPAT
|
||||
extern long compat_keyctl_dh_compute(struct keyctl_dh_params __user *params,
|
||||
char __user *buffer, size_t buflen,
|
||||
struct compat_keyctl_kdf_params __user *kdf);
|
||||
|
@ -279,7 +279,7 @@ static inline long keyctl_dh_compute(struct keyctl_dh_params __user *params,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KEYS_COMPAT
|
||||
#ifdef CONFIG_COMPAT
|
||||
static inline long compat_keyctl_dh_compute(
|
||||
struct keyctl_dh_params __user *params,
|
||||
char __user *buffer, size_t buflen,
|
||||
|
|
|
@ -309,6 +309,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
|
|||
return rc;
|
||||
|
||||
rc = tpm2_unseal_cmd(chip, payload, options, blob_handle);
|
||||
tpm2_flush_context(chip, blob_handle);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -2,3 +2,9 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
|
||||
|
||||
python -m unittest -v tpm2_tests.SmokeTest
|
||||
python -m unittest -v tpm2_tests.AsyncTest
|
||||
|
||||
CLEAR_CMD=$(which tpm2_clear)
|
||||
if [ -n $CLEAR_CMD ]; then
|
||||
tpm2_clear -T device
|
||||
fi
|
||||
|
|
|
@ -6,8 +6,8 @@ import socket
|
|||
import struct
|
||||
import sys
|
||||
import unittest
|
||||
from fcntl import ioctl
|
||||
|
||||
import fcntl
|
||||
import select
|
||||
|
||||
TPM2_ST_NO_SESSIONS = 0x8001
|
||||
TPM2_ST_SESSIONS = 0x8002
|
||||
|
@ -352,6 +352,7 @@ def hex_dump(d):
|
|||
class Client:
|
||||
FLAG_DEBUG = 0x01
|
||||
FLAG_SPACE = 0x02
|
||||
FLAG_NONBLOCK = 0x04
|
||||
TPM_IOC_NEW_SPACE = 0xa200
|
||||
|
||||
def __init__(self, flags = 0):
|
||||
|
@ -362,13 +363,27 @@ class Client:
|
|||
else:
|
||||
self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)
|
||||
|
||||
if (self.flags & Client.FLAG_NONBLOCK):
|
||||
flags = fcntl.fcntl(self.tpm, fcntl.F_GETFL)
|
||||
flags |= os.O_NONBLOCK
|
||||
fcntl.fcntl(self.tpm, fcntl.F_SETFL, flags)
|
||||
self.tpm_poll = select.poll()
|
||||
|
||||
def close(self):
|
||||
self.tpm.close()
|
||||
|
||||
def send_cmd(self, cmd):
|
||||
self.tpm.write(cmd)
|
||||
|
||||
if (self.flags & Client.FLAG_NONBLOCK):
|
||||
self.tpm_poll.register(self.tpm, select.POLLIN)
|
||||
self.tpm_poll.poll(10000)
|
||||
|
||||
rsp = self.tpm.read()
|
||||
|
||||
if (self.flags & Client.FLAG_NONBLOCK):
|
||||
self.tpm_poll.unregister(self.tpm)
|
||||
|
||||
if (self.flags & Client.FLAG_DEBUG) != 0:
|
||||
sys.stderr.write('cmd' + os.linesep)
|
||||
sys.stderr.write(hex_dump(cmd) + os.linesep)
|
||||
|
|
|
@ -288,3 +288,16 @@ class SpaceTest(unittest.TestCase):
|
|||
|
||||
self.assertEqual(rc, tpm2.TPM2_RC_COMMAND_CODE |
|
||||
tpm2.TSS2_RESMGR_TPM_RC_LAYER)
|
||||
|
||||
class AsyncTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
logging.basicConfig(filename='AsyncTest.log', level=logging.DEBUG)
|
||||
|
||||
def test_async(self):
|
||||
log = logging.getLogger(__name__)
|
||||
log.debug(sys._getframe().f_code.co_name)
|
||||
|
||||
async_client = tpm2.Client(tpm2.Client.FLAG_NONBLOCK)
|
||||
log.debug("Calling get_cap in a NON_BLOCKING mode")
|
||||
async_client.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_LOADED_SESSION)
|
||||
async_client.close()
|
||||
|
|
Loading…
Reference in a new issue