[PATCH] KEYS: trusted: tee: use tee_shm_register_alloc_buf()
Jens Wiklander
jens.wiklander at linaro.org
Thu Aug 3 12:35:15 UTC 2023
Prior to this patch was trusted_tee_seal() and trusted_tee_get_random()
relying on tee_shm_register_kernel_buf() to share memory with the TEE.
Depending on the memory allocation pattern the pages holding the
registered buffers overlap with other buffers also shared with the TEE.
The OP-TEE driver using the old SMC based ABI permits overlapping shared
buffers, but with the new FF-A based ABI each physical page may only
be registered once.
Fix this problem by allocating a temporary page aligned shared memory
buffer to be used as a bounce buffer for the needed data buffers.
Since TEE trusted keys doesn't depend on registered shared memory
support any longer remove that explicit dependency when opening a
context to the TEE.
Signed-off-by: Jens Wiklander <jens.wiklander at linaro.org>
---
security/keys/trusted-keys/trusted_tee.c | 68 +++++++++++++-----------
1 file changed, 36 insertions(+), 32 deletions(-)
diff --git a/security/keys/trusted-keys/trusted_tee.c b/security/keys/trusted-keys/trusted_tee.c
index ac3e270ade69..3085343c489a 100644
--- a/security/keys/trusted-keys/trusted_tee.c
+++ b/security/keys/trusted-keys/trusted_tee.c
@@ -8,6 +8,7 @@
#include <linux/err.h>
#include <linux/key-type.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -65,38 +66,37 @@ static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob)
int ret;
struct tee_ioctl_invoke_arg inv_arg;
struct tee_param param[4];
- struct tee_shm *reg_shm_in = NULL, *reg_shm_out = NULL;
+ struct tee_shm *shm;
+ uint8_t *buf;
memset(&inv_arg, 0, sizeof(inv_arg));
memset(¶m, 0, sizeof(param));
- reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
- p->key_len);
- if (IS_ERR(reg_shm_in)) {
- dev_err(pvt_data.dev, "key shm register failed\n");
- return PTR_ERR(reg_shm_in);
+ shm = tee_shm_alloc_kernel_buf(pvt_data.ctx,
+ p->key_len + sizeof(p->blob));
+ if (IS_ERR(shm)) {
+ dev_err(pvt_data.dev, "key shm alloc failed\n");
+ return PTR_ERR(shm);
}
-
- reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob,
- sizeof(p->blob));
- if (IS_ERR(reg_shm_out)) {
- dev_err(pvt_data.dev, "blob shm register failed\n");
- ret = PTR_ERR(reg_shm_out);
+ buf = tee_shm_get_va(shm, 0);
+ if (IS_ERR(buf)) {
+ ret = PTR_ERR(buf);
goto out;
}
+ memcpy(buf, p->key, p->key_len);
inv_arg.func = TA_CMD_SEAL;
inv_arg.session = pvt_data.session_id;
inv_arg.num_params = 4;
param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
- param[0].u.memref.shm = reg_shm_in;
+ param[0].u.memref.shm = shm;
param[0].u.memref.size = p->key_len;
param[0].u.memref.shm_offs = 0;
param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
- param[1].u.memref.shm = reg_shm_out;
+ param[1].u.memref.shm = shm;
param[1].u.memref.size = sizeof(p->blob);
- param[1].u.memref.shm_offs = 0;
+ param[1].u.memref.shm_offs = p->key_len;
ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
if ((ret < 0) || (inv_arg.ret != 0)) {
@@ -104,14 +104,13 @@ static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob)
inv_arg.ret);
ret = -EFAULT;
} else {
+ memcpy(p->blob, buf + p->key_len,
+ min(param[1].u.memref.size, sizeof(p->blob)));
p->blob_len = param[1].u.memref.size;
}
out:
- if (reg_shm_out)
- tee_shm_free(reg_shm_out);
- if (reg_shm_in)
- tee_shm_free(reg_shm_in);
+ tee_shm_free(shm);
return ret;
}
@@ -166,11 +165,9 @@ static int trusted_tee_unseal(struct trusted_key_payload *p, char *datablob)
p->key_len = param[1].u.memref.size;
}
+ tee_shm_free(reg_shm_out);
out:
- if (reg_shm_out)
- tee_shm_free(reg_shm_out);
- if (reg_shm_in)
- tee_shm_free(reg_shm_in);
+ tee_shm_free(reg_shm_in);
return ret;
}
@@ -183,15 +180,21 @@ static int trusted_tee_get_random(unsigned char *key, size_t key_len)
int ret;
struct tee_ioctl_invoke_arg inv_arg;
struct tee_param param[4];
- struct tee_shm *reg_shm = NULL;
+ struct tee_shm *shm;
+ void *buf;
memset(&inv_arg, 0, sizeof(inv_arg));
memset(¶m, 0, sizeof(param));
- reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, key, key_len);
- if (IS_ERR(reg_shm)) {
- dev_err(pvt_data.dev, "key shm register failed\n");
- return PTR_ERR(reg_shm);
+ shm = tee_shm_alloc_kernel_buf(pvt_data.ctx, key_len);
+ if (IS_ERR(shm)) {
+ dev_err(pvt_data.dev, "key shm alloc failed\n");
+ return PTR_ERR(shm);
+ }
+ buf = tee_shm_get_va(shm, 0);
+ if (IS_ERR(buf)) {
+ ret = PTR_ERR(buf);
+ goto out;
}
inv_arg.func = TA_CMD_GET_RANDOM;
@@ -199,7 +202,7 @@ static int trusted_tee_get_random(unsigned char *key, size_t key_len)
inv_arg.num_params = 4;
param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
- param[0].u.memref.shm = reg_shm;
+ param[0].u.memref.shm = shm;
param[0].u.memref.size = key_len;
param[0].u.memref.shm_offs = 0;
@@ -209,18 +212,19 @@ static int trusted_tee_get_random(unsigned char *key, size_t key_len)
inv_arg.ret);
ret = -EFAULT;
} else {
+ memcpy(key, buf, min(param[0].u.memref.size, key_len));
ret = param[0].u.memref.size;
}
- tee_shm_free(reg_shm);
+out:
+ tee_shm_free(shm);
return ret;
}
static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
{
- if (ver->impl_id == TEE_IMPL_ID_OPTEE &&
- ver->gen_caps & TEE_GEN_CAP_REG_MEM)
+ if (ver->impl_id == TEE_IMPL_ID_OPTEE)
return 1;
else
return 0;
--
2.34.1
More information about the Linux-security-module-archive
mailing list