Hi,
This patch set allocates the restricted DMA-bufs via the TEE subsystem.
The TEE subsystem handles the DMA-buf allocations since it is the TEE
(OP-TEE, AMD-TEE, TS-TEE, or perhaps a future QCOMTEE) which sets up the
restrictions for the memory used for the DMA-bufs.
I've added a new IOCTL, TEE_IOC_RSTMEM_ALLOC, to allocate the restricted
DMA-bufs. This IOCTL reaches the backend TEE driver, allowing it to choose
how to allocate the restricted physical memory.
TEE_IOC_RSTMEM_ALLOC takes in addition to a size and flags parameters also
a use-case parameter. This is used by the backend TEE driver to decide on
allocation policy and which devices should be able to access the memory.
Three use-cases (Secure Video Playback, Trusted UI, and Secure Video
Recording) has been identified so far to serve as examples of what can be
expected. More use-cases can be added in userspace ABI, but it's up to the
backend TEE drivers to provide the implementation.
Each use-case has it's own restricted memory pool since different use-cases
requires isolation from different parts of the system. A restricted memory
pool can be based on a static carveout instantiated while probing the TEE
backend driver, or dynamically allocated from CMA and made restricted as
needed by the TEE.
This can be tested on QEMU with the following steps:
repo init -u https://github.com/jenswi-linaro/manifest.git -m qemu_v8.xml \
-b prototype/sdp-v4
repo sync -j8
cd build
make toolchains -j$(nproc)
make SPMC_AT_EL=1 all -j$(nproc)
make SPMC_AT_EL=1 run-only
# login and at the prompt:
xtest --sdp-basic
The SPMC_AT_EL=1 parameter configures the build with FF-A and an SPMC at
S-EL1 inside OP-TEE. The parameter can be changed into SPMC_AT_EL=n to test
without FF-A using the original SMC ABI instead. Please remember to do
%rm -rf ../trusted-firmware-a/build/qemu
for TF-A to be rebuilt properly using the new configuration.
https://optee.readthedocs.io/en/latest/building/prerequisites.html
list dependencies needed to build the above.
The tests are pretty basic, mostly checking that a Trusted Application in
the secure world can access and manipulate the memory. There are also some
negative tests for out of bounds buffers etc.
Thanks,
Jens
Changes since V3:
* Make the use_case and flags field in struct tee_shm u32's instead of
u16's
* Add more description for TEE_IOC_RSTMEM_ALLOC in the header file
* Import namespace DMA_BUF in module tee, reported by lkp(a)intel.com
* Added a note in the commit message for "optee: account for direction
while converting parameters" why it's needed
* Factor out dynamic restricted memory allocation from
"optee: support restricted memory allocation" into two new commits
"optee: FF-A: dynamic restricted memory allocation" and
"optee: smc abi: dynamic restricted memory allocation"
* Guard CMA usage with #ifdef CONFIG_CMA, effectively disabling dynamic
restricted memory allocate if CMA isn't configured
Changes since the V2 RFC:
* Based on v6.12
* Replaced the flags for SVP and Trusted UID memory with a u32 field with
unique id for each use case
* Added dynamic allocation of restricted memory pools
* Added OP-TEE ABI both with and without FF-A for dynamic restricted memory
* Added support for FF-A with FFA_LEND
Changes since the V1 RFC:
* Based on v6.11
* Complete rewrite, replacing the restricted heap with TEE_IOC_RSTMEM_ALLOC
Changes since Olivier's post [2]:
* Based on Yong Wu's post [1] where much of dma-buf handling is done in
the generic restricted heap
* Simplifications and cleanup
* New commit message for "dma-buf: heaps: add Linaro restricted dmabuf heap
support"
* Replaced the word "secure" with "restricted" where applicable
Jens Wiklander (6):
tee: add restricted memory allocation
optee: account for direction while converting parameters
optee: sync secure world ABI headers
optee: support restricted memory allocation
optee: FF-A: dynamic restricted memory allocation
optee: smc abi: dynamic restricted memory allocation
drivers/tee/Makefile | 1 +
drivers/tee/optee/Makefile | 1 +
drivers/tee/optee/call.c | 10 +-
drivers/tee/optee/core.c | 1 +
drivers/tee/optee/ffa_abi.c | 178 +++++++++++++-
drivers/tee/optee/optee_ffa.h | 27 ++-
drivers/tee/optee/optee_msg.h | 65 ++++-
drivers/tee/optee/optee_private.h | 75 ++++--
drivers/tee/optee/optee_smc.h | 71 +++++-
drivers/tee/optee/rpc.c | 31 ++-
drivers/tee/optee/rstmem.c | 388 ++++++++++++++++++++++++++++++
drivers/tee/optee/smc_abi.c | 213 ++++++++++++++--
drivers/tee/tee_core.c | 38 ++-
drivers/tee/tee_private.h | 2 +
drivers/tee/tee_rstmem.c | 201 ++++++++++++++++
drivers/tee/tee_shm.c | 2 +
drivers/tee/tee_shm_pool.c | 69 +++++-
include/linux/tee_core.h | 15 ++
include/linux/tee_drv.h | 2 +
include/uapi/linux/tee.h | 44 +++-
20 files changed, 1358 insertions(+), 76 deletions(-)
create mode 100644 drivers/tee/optee/rstmem.c
create mode 100644 drivers/tee/tee_rstmem.c
base-commit: fac04efc5c793dccbd07e2d59af9f90b7fc0dca4
--
2.43.0
This patch series introduces a Trusted Execution Environment (TEE)
driver for Qualcomm TEE (QTEE). QTEE enables Trusted Applications (TAs)
and services to run securely. It uses an object-based interface, where
each service is an object with sets of operations. Clients can invoke
these operations on objects, which can generate results, including other
objects. For example, an object can load a TA and return another object
that represents the loaded TA, allowing access to its services.
Kernel and userspace services are also available to QTEE through a
similar approach. QTEE makes callback requests that are converted into
object invocations. These objects can represent services within the
kernel or userspace process.
Note: This patch series focuses on QTEE objects and userspace services.
Linux already provides a TEE subsystem, which is described in [1]. The
tee subsystem provides a generic ioctl interface, TEE_IOC_INVOKE, which
can be used by userspace to talk to a TEE backend driver. We extend the
Linux TEE subsystem to understand object parameters and an ioctl call so
client can invoke objects in QTEE:
- TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_*
- TEE_IOC_OBJECT_INVOKE
The existing ioctl calls TEE_IOC_SUPPL_RECV and TEE_IOC_SUPPL_SEND are
used for invoking services in the userspace process by QTEE.
The TEE backend driver uses the QTEE Transport Message to communicate
with QTEE. Interactions through the object INVOKE interface are
translated into QTEE messages. Likewise, object invocations from QTEE
for userspace objects are converted into SEND/RECV ioctl calls to
supplicants.
The details of QTEE Transport Message to communicate with QTEE is
available in [PATCH 10/10] Documentation: tee: Add Qualcomm TEE driver.
This patch series has been tested for basic QTEE object invocations and
callback requests, including loading a TA and requesting services form
the TA. However, the test platform is currently being prepared for
upstream availability and will soon be accessible to the community for
further validation. I will share updates as the platform become
available.
[1] https://www.kernel.org/doc/Documentation/tee.txt
Signed-off-by: Amirreza Zarrabi <quic_azarrabi(a)quicinc.com>
---
Amirreza Zarrabi (10):
tee: allow a driver to allocate a tee_device without a pool
tee: add TEE_IOCTL_PARAM_ATTR_TYPE_MEMBUF
tee: add TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF
firmware: qcom: scm: add support for object invocation
qcomtee: implement object invoke support
qcomtee: add primordial object
dt-bindings: arm: qcomtee: add QTEE driver devicetree binding for TEE subsystem
tee: add Qualcomm TEE driver
arm64: dts: qcom: sm8650: add support for QTEE
Documentation: tee: Add Qualcomm TEE driver
.../devicetree/bindings/arm/firmware/qcom,tee.yaml | 34 +
Documentation/tee/index.rst | 1 +
Documentation/tee/qtee.rst | 143 ++++
arch/arm64/boot/dts/qcom/sm8650.dtsi | 4 +
drivers/firmware/qcom/qcom_scm.c | 60 ++
drivers/firmware/qcom/qcom_scm.h | 7 +
drivers/tee/Kconfig | 1 +
drivers/tee/Makefile | 1 +
drivers/tee/qcomtee/Kconfig | 10 +
drivers/tee/qcomtee/Makefile | 9 +
drivers/tee/qcomtee/async.c | 153 ++++
drivers/tee/qcomtee/call.c | 707 ++++++++++++++++
drivers/tee/qcomtee/core.c | 942 +++++++++++++++++++++
drivers/tee/qcomtee/primordial_obj.c | 63 ++
drivers/tee/qcomtee/qcom_scm.c | 36 +
drivers/tee/qcomtee/qcomtee_msg.h | 217 +++++
drivers/tee/qcomtee/qcomtee_private.h | 218 +++++
drivers/tee/qcomtee/release.c | 66 ++
drivers/tee/qcomtee/user_obj.c | 625 ++++++++++++++
drivers/tee/tee_core.c | 113 ++-
include/linux/firmware/qcom/qcom_scm.h | 9 +
include/linux/firmware/qcom/qcom_tee.h | 284 +++++++
include/linux/tee_core.h | 4 +
include/linux/tee_drv.h | 12 +
include/uapi/linux/tee.h | 54 +-
25 files changed, 3765 insertions(+), 8 deletions(-)
---
base-commit: f486c8aa16b8172f63bddc70116a0c897a7f3f02
change-id: 20241202-qcom-tee-using-tee-ss-without-mem-obj-362c66340527
Best regards,
--
Amirreza Zarrabi <quic_azarrabi(a)quicinc.com>
OP-TEE supplicant is a user-space daemon and it's possible for it
being crashed or killed in the middle of processing an OP-TEE RPC call.
It becomes more complicated when there is incorrect shutdown ordering
of the supplicant process vs the OP-TEE client application which can
eventually lead to system hang-up waiting for the closure of the client
application.
In order to gracefully handle this scenario, let's add a long enough
timeout to wait for supplicant to process requests. In case there is a
timeout then we return a proper error code for the RPC request.
Signed-off-by: Sumit Garg <sumit.garg(a)linaro.org>
---
drivers/tee/optee/supp.c | 58 +++++++++++++++++++++++++---------------
1 file changed, 36 insertions(+), 22 deletions(-)
diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
index 322a543b8c27..92e86ac4cdd4 100644
--- a/drivers/tee/optee/supp.c
+++ b/drivers/tee/optee/supp.c
@@ -7,6 +7,15 @@
#include <linux/uaccess.h>
#include "optee_private.h"
+/*
+ * OP-TEE supplicant timeout, the user-space supplicant may get
+ * crashed or killed while servicing an RPC call. This will just lead
+ * to OP-TEE client hung indefinitely just waiting for supplicant to
+ * serve requests which isn't expected. It is rather expected to fail
+ * gracefully with a timeout which is long enough.
+ */
+#define SUPP_TIMEOUT (msecs_to_jiffies(10000))
+
struct optee_supp_req {
struct list_head link;
@@ -52,8 +61,10 @@ void optee_supp_release(struct optee_supp *supp)
/* Abort all queued requests */
list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
- list_del(&req->link);
- req->in_queue = false;
+ if (req->in_queue) {
+ list_del(&req->link);
+ req->in_queue = false;
+ }
req->ret = TEEC_ERROR_COMMUNICATION;
complete(&req->c);
}
@@ -82,6 +93,7 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
struct optee_supp_req *req;
bool interruptable;
u32 ret;
+ int res = 1;
/*
* Return in case there is no supplicant available and
@@ -108,28 +120,28 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
/* Tell an eventual waiter there's a new request */
complete(&supp->reqs_c);
- /*
- * Wait for supplicant to process and return result, once we've
- * returned from wait_for_completion(&req->c) successfully we have
- * exclusive access again.
- */
- while (wait_for_completion_interruptible(&req->c)) {
+ /* Wait for supplicant to process and return result */
+ while (res) {
+ res = wait_for_completion_interruptible_timeout(&req->c,
+ SUPP_TIMEOUT);
+ /* Check if supplicant served the request */
+ if (res > 0)
+ break;
+
mutex_lock(&supp->mutex);
+ /*
+ * There's no supplicant available and since the supp->mutex
+ * currently is held none can become available until the mutex
+ * released again.
+ *
+ * Interrupting an RPC to supplicant is only allowed as a way
+ * of slightly improving the user experience in case the
+ * supplicant hasn't been started yet. During normal operation
+ * the supplicant will serve all requests in a timely manner and
+ * interrupting then wouldn't make sense.
+ */
interruptable = !supp->ctx;
- if (interruptable) {
- /*
- * There's no supplicant available and since the
- * supp->mutex currently is held none can
- * become available until the mutex released
- * again.
- *
- * Interrupting an RPC to supplicant is only
- * allowed as a way of slightly improving the user
- * experience in case the supplicant hasn't been
- * started yet. During normal operation the supplicant
- * will serve all requests in a timely manner and
- * interrupting then wouldn't make sense.
- */
+ if (interruptable || (res == 0)) {
if (req->in_queue) {
list_del(&req->link);
req->in_queue = false;
@@ -141,6 +153,8 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
req->ret = TEEC_ERROR_COMMUNICATION;
break;
}
+ if (res == 0)
+ req->ret = TEE_ERROR_TIMEOUT;
}
ret = req->ret;
--
2.43.0
There has been a recent change in OP-TEE to print 8 and 16 character
commit id for 32bit and 64bit architecture respectively.
In case if commit id is starting with 0 like 04d1c612ec7beaede073b8c
it is printing revision as below removing leading 0
"optee: revision 4.4 (4d1c612ec7beaed)"
Signed-off-by: Sahil Malhotra <sahil.malhotra(a)nxp.com>
---
drivers/tee/optee/smc_abi.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index e9456e3e74cc..eb51dc18f32d 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1272,8 +1272,9 @@ static void optee_msg_get_os_revision(optee_invoke_fn *invoke_fn)
&res.smccc);
if (res.result.build_id)
- pr_info("revision %lu.%lu (%08lx)", res.result.major,
- res.result.minor, res.result.build_id);
+ pr_info("revision %lu.%lu (%0*lx)", res.result.major,
+ res.result.minor, (int)sizeof(res.result.build_id) * 2,
+ res.result.build_id);
else
pr_info("revision %lu.%lu", res.result.major, res.result.minor);
}
--
2.34.1
Hi, not sure if this is a good place to ask, however I see that OPTEE
developers are highly involved in this topic so I decided to ask.
Short background - we've been working on an embedded system based on
Layerscape 1028A SoC. On this platform we've been using TFA (bl2, el3
runtime services), OPTEE as BL32 and u-boot as BL33. In the previous,
older platforms we usually stored u-boot's environment in let's say
"traditional way", we just stored the env on some offset of the eMMC
device, however I see that on this particular, new platform there are
some better possibilities, like combining OPTEE, EDKII StandaloneMM
and u-boot efivars implementation to store EFI variables in RPMB on
eMMC which seems to be more secure, UEFI compliant way. The aspect I'm
unsure of is - does it make sense to utilize these capabilities if we
want to only use it to store some u-boot's writable env variables and
not utilize features like UEFI SecureBoot (at least for now, it may
change it in the future)?
I would be grateful for some advice.
Best regards
Patryk
Hi All,
We are currently working on standard PKCS#11 TA and I'm new to this topic
(PKCS11, OP-TEE,TA).
Please go through and share your inputs on the following queries.
-> slot
How do we know how many slots are supported in my device?
Is it based on the physical interface of the device or how do we
find the list of available slots without pkcs11-tool?
Please share the details with an example.
-> token
Is token is a kind of virtual to hold different objects(keys, cert
and so on).
Can one token have private, public, leaf cert, intermediate ca
cert, root ca cart and so on or any limitations on the number of objects in
a token?
Can we have each token be specific to the object ( for example ,
token1 will have cert, token 2 will have key, token 3 will have seed/client
cert )?
How many tokens maximum support on each slot?
-> As part of pkcs11-tool, we have been using SO-PIN, user PIN,
token/label name which are more specific to security.
If the normal world/REE is compromised, any sensitive data it holds,
including PINs and tokens, could be exposed.
Do we have any access control mechanism to avoid this security issue
( in PKCS11 TA, OP-TEE context).
Thanks,
Murali.S
Hi,
This patch set allocates the restricted DMA-bufs via the TEE subsystem.
This a big update compared to the previous patch set [1].
The TEE subsystem handles the DMA-buf allocations since it is the TEE
(OP-TEE, AMD-TEE, TS-TEE, or perhaps a future QTEE) which sets up the
restrictions for the memory used for the DMA-bufs.
I've added a new IOCTL, TEE_IOC_RSTMEM_ALLOC, to allocate the restricted
DMA-bufs. This IOCTL reaches the backend TEE driver, allowing it to choose
how to allocate the restricted physical memory.
TEE_IOC_RSTMEM_ALLOC takes in addition to a size and flags parameters also
a use-case parameter. This is used by the backend TEE driver to decide on
allocation policy and which devices should be able to access the memory.
Three use-cases (Secure Video Playback, Trusted UI, and Secure Video
Recording) has been identified so far to serve as examples of what can be
expected. More use-cases can be added in userspace ABI, but it's up to the
backend TEE drivers to provide the implementation.
Each use-case has it's own restricted memory pool since different use-cases
requires isolation from different parts of the system. A restricted memory
pool can be based on a static carveout instantiated while probing the TEE
backend driver, or dynamically allocated from CMA and made restricted as
needed by the TEE.
This can be tested on QEMU with the following steps:
repo init -u https://github.com/jenswi-linaro/manifest.git -m qemu_v8.xml \
-b prototype/sdp-v3
repo sync -j8
cd build
make toolchains -j$(nproc)
make SPMC_AT_EL=1 all -j$(nproc)
make SPMC_AT_EL=1 run-only
# login and at the prompt:
xtest --sdp-basic
The SPMC_AT_EL=1 parameter configures the build with FF-A and an SPMC at
S-EL1 inside OP-TEE. The parameter can be changed into SPMC_AT_EL=n to test
without FF-A using the original SMC ABI instead. Please remember to do
%rm -rf ../trusted-firmware-a/build/qemu
for TF-A to be rebuilt properly using the new configuration.
https://optee.readthedocs.io/en/latest/building/prerequisites.html
list dependencies needed to build the above.
The tests are pretty basic, mostly checking that a Trusted Application in
the secure world can access and manipulate the memory. There are also some
negative tests for out of bounds buffers etc.
Thanks,
Jens
[1] https://lore.kernel.org/lkml/20241015101716.740829-1-jens.wiklander@linaro.…
Changes since the V2 RFC:
* Based on v6.12
* Replaced the flags for SVP and Trusted UID memory with a u32 field with
unique id for each use case
* Added dynamic allocation of restricted memory pools
* Added OP-TEE ABI both with and without FF-A for dynamic restricted memory
* Added support for FF-A with FFA_LEND
Changes since the V1 RFC:
* Based on v6.11
* Complete rewrite, replacing the restricted heap with TEE_IOC_RSTMEM_ALLOC
Changes since Olivier's post [2]:
* Based on Yong Wu's post [1] where much of dma-buf handling is done in
the generic restricted heap
* Simplifications and cleanup
* New commit message for "dma-buf: heaps: add Linaro restricted dmabuf heap
support"
* Replaced the word "secure" with "restricted" where applicable
Jens Wiklander (4):
tee: add restricted memory allocation
optee: account for direction while converting parameters
optee: sync secure world ABI headers
optee: support restricted memory allocation
drivers/tee/Makefile | 1 +
drivers/tee/optee/Makefile | 1 +
drivers/tee/optee/call.c | 10 +-
drivers/tee/optee/core.c | 1 +
drivers/tee/optee/ffa_abi.c | 178 +++++++++++++-
drivers/tee/optee/optee_ffa.h | 27 ++-
drivers/tee/optee/optee_msg.h | 65 ++++-
drivers/tee/optee/optee_private.h | 75 ++++--
drivers/tee/optee/optee_smc.h | 71 +++++-
drivers/tee/optee/rpc.c | 31 ++-
drivers/tee/optee/rstmem.c | 380 ++++++++++++++++++++++++++++++
drivers/tee/optee/smc_abi.c | 214 +++++++++++++++--
drivers/tee/tee_core.c | 37 ++-
drivers/tee/tee_private.h | 2 +
drivers/tee/tee_rstmem.c | 201 ++++++++++++++++
drivers/tee/tee_shm.c | 2 +
drivers/tee/tee_shm_pool.c | 69 +++++-
include/linux/tee_core.h | 15 ++
include/linux/tee_drv.h | 4 +-
include/uapi/linux/tee.h | 37 ++-
20 files changed, 1344 insertions(+), 77 deletions(-)
create mode 100644 drivers/tee/optee/rstmem.c
create mode 100644 drivers/tee/tee_rstmem.c
--
2.43.0
The TEE subsystem manages three main structures: tee_device, the device
that represents the TEE; tee_context, the context that represents the
TEE client; and tee_shm, which represents the shared memory with the
TEE. When a tee_device is opened, it creates a tee_context instance. The
tee_shm is created for the tee_device when allocating shared memory with
the TEE but is linked to a context. The lifespan of the device is
determined by the presence of context and shared memory, while the
lifespan of a context depends on the client closing the device.
This behavior has been modified, making the lifespan of context
dependent on shared memory. If a client closes the device but doesn’t
release the shared memory, the linked context will remain active,
preventing the release callback from freeing resources in the TEE. This
could lead to a deadlock if the TEE holds a reference to the shared
memory and relies on the release callback to remove the reference.
In this pachset we introduce orphan tee_shm and default tee_context.
When a shared memory becomes orphan because its associated context is
released, it no longer has a tee_context. One method to differentiate
between orphaned and regular shared memory is to use NULL as the linked
context. However, this can cause issues if releasing the shared memory
triggers additional calls, like those to the supplicant, which require a
valid context. Instead of using NULL, an internal tee_context for the
driver can be used.
The driver relies on tee_device_unregister which is a blocking calls
waiting for all context to be released and all shared memory to be freed
before unloading the driver. This means that all contexts, including
internal context, should be closed before tee_device_unregister can
proceed. This can introduce a short window where there is no valid
context to use when releasing the shared memory. The default tee_context
has lifespan similar to the device.
For an orphan tee_shm, default context is used.
This has not been tested. Looking for feedback if this is a reasonable
change.
Signed-off-by: Amirreza Zarrabi <quic_azarrabi(a)quicinc.com>
---
Amirreza Zarrabi (3):
tee: revert removal of redundant teedev in struct tee_shm
tee: revert removal of linked list of struct tee_shm
tee: introduce orphan tee_shm and default context
drivers/tee/optee/core.c | 2 +-
drivers/tee/optee/ffa_abi.c | 2 +-
drivers/tee/optee/smc_abi.c | 2 +-
drivers/tee/tee_core.c | 84 +++++++++++++++++++++++++++++----------------
drivers/tee/tee_private.h | 3 --
drivers/tee/tee_shm.c | 41 ++++++++++++----------
include/linux/tee_core.h | 15 ++++++++
include/linux/tee_drv.h | 13 ++++---
8 files changed, 100 insertions(+), 62 deletions(-)
---
base-commit: ae58226b89ac0cffa05ba7357733776542e40216
change-id: 20241120-fix-tee_shm-refcount-upstream-c671b89fbe67
Best regards,
--
Amirreza Zarrabi <quic_azarrabi(a)quicinc.com>