You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by yu...@apache.org on 2025/09/30 02:58:04 UTC

(teaclave-trustzone-sdk) 02/03: optee-teec: clippy default enforcement

This is an automated email from the ASF dual-hosted git repository.

yuanz pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/teaclave-trustzone-sdk.git

commit c4b7d4d171ae17728c45ad37b9a0abbbb909d58d
Author: Yuan Zhuang <yu...@apache.org>
AuthorDate: Thu Sep 25 08:39:12 2025 +0000

    optee-teec: clippy default enforcement
---
 .github/workflows/reuse_test.yml                |  1 +
 optee-teec/macros/src/lib.rs                    | 60 ++++++++++++++++---------
 optee-teec/optee-teec-sys/src/tee_client_api.rs |  2 +-
 optee-teec/src/extension.rs                     |  8 ++--
 optee-teec/src/operation.rs                     |  2 +-
 optee-teec/src/parameter.rs                     | 12 ++---
 6 files changed, 53 insertions(+), 32 deletions(-)

diff --git a/.github/workflows/reuse_test.yml b/.github/workflows/reuse_test.yml
index 6980089..407328a 100644
--- a/.github/workflows/reuse_test.yml
+++ b/.github/workflows/reuse_test.yml
@@ -61,6 +61,7 @@ jobs:
 
           # Clippy checks
           (cd optee-utee && cargo clippy --target aarch64-unknown-linux-gnu -- -D warnings)
+          (cd optee-teec && cargo clippy --target aarch64-unknown-linux-gnu -- -D warnings)
 
   # Cross-compile on host and run tests in QEMU
   #
diff --git a/optee-teec/macros/src/lib.rs b/optee-teec/macros/src/lib.rs
index b337352..ddabc33 100644
--- a/optee-teec/macros/src/lib.rs
+++ b/optee-teec/macros/src/lib.rs
@@ -39,12 +39,9 @@ pub fn plugin_init(_args: TokenStream, input: TokenStream) -> TokenStream {
 
     // check the function signature
     let valid_signature = f_sig.constness.is_none()
-        && match f_vis {
-            syn::Visibility::Inherited => true,
-            _ => false,
-        }
+        && matches!(f_vis, syn::Visibility::Inherited)
         && f_sig.abi.is_none()
-        && f_inputs.len() == 0
+        && f_inputs.is_empty()
         && f_sig.generics.where_clause.is_none()
         && f_sig.variadic.is_none()
         && check_return_type(&f);
@@ -83,7 +80,7 @@ fn check_return_type(item_fn: &syn::ItemFn) -> bool {
             }
         }
     }
-    return false;
+    false
 }
 
 /// Attribute to declare the invoke function of a plugin
@@ -101,10 +98,7 @@ pub fn plugin_invoke(_args: TokenStream, input: TokenStream) -> TokenStream {
 
     // check the function signature
     let valid_signature = f_sig.constness.is_none()
-        && match f_vis {
-            syn::Visibility::Inherited => true,
-            _ => false,
-        }
+        && matches!(f_vis, syn::Visibility::Inherited)
         && f_sig.abi.is_none()
         && f_inputs.len() == 1
         && f_sig.generics.where_clause.is_none()
@@ -129,11 +123,39 @@ pub fn plugin_invoke(_args: TokenStream, input: TokenStream) -> TokenStream {
         .into_token_stream();
 
     quote!(
-        // temporary workaround for this error:
-        // error: this public function might dereference a raw pointer but is not marked `unsafe`
-        // should remove this allow macro when fix clippy errors of optee-* crates
-        #[allow(clippy::not_unsafe_ptr_arg_deref)]
-        pub fn _plugin_invoke(
+        /// # Safety
+        ///
+        /// The `_plugin_invoke` function is the `extern "C"` entrypoint called by OP-TEE OS.  
+        /// This SDK allows developers to implement the inner logic for a Normal World plugin in Rust.
+        /// More about plugins:
+        /// https://optee.readthedocs.io/en/latest/architecture/globalplatform_api.html#loadable-plugins-framework
+        ///
+        /// According to Clippy checks, any FFI function taking raw pointers as parameters
+        /// must be marked `unsafe`. This applies here because the function directly
+        /// dereferences `data` and `out_len`.
+        ///
+        /// ## Security assumptions
+        /// The caller (OP-TEE OS) must ensure:
+        /// - `data` points to valid memory for reads and writes of at least `in_len` bytes
+        /// - `out_len` is a valid, writable, and properly aligned pointer to a `u32`
+        /// - If `in_len == 0`, `data` may be null; otherwise it must be non-null
+        ///
+        /// Additional guarantees enforced by `PluginParameters` in this SDK:
+        /// - The output length (`outslice.len()`) will never exceed `in_len`
+        ///   because [`PluginParameters::set_buf_from_slice`] checks and rejects overflows.
+        /// - Input and output share the same buffer (`inout`), so overlap is intentional
+        ///   and safely handled by [`PluginParameters::set_buf_from_slice`].
+        ///
+        /// ## Scenarios
+        /// - **Valid empty call**: `data = null`, `in_len = 0` → allowed; produces an empty output.
+        /// - **Normal call**: `data` points to a buffer of size `in_len`; the plugin writes
+        ///   up to `in_len` bytes and updates `*out_len`.
+        /// - **Overflow attempt**: plugin inner logic (developer code) tries to return
+        ///   more bytes than `in_len` → rejected by `set_buf_from_slice`, error returned.
+        /// - **Invalid pointers**: if `data` or `out_len` are invalid (null, dangling, misaligned,
+        ///   or pointing to read-only memory), dereferencing them causes undefined behavior.
+        ///   This must be prevented by the caller (OP-TEE OS).
+        pub unsafe fn _plugin_invoke(
             cmd: u32,
             sub_cmd: u32,
             data: *mut core::ffi::c_char,
@@ -143,16 +165,14 @@ pub fn plugin_invoke(_args: TokenStream, input: TokenStream) -> TokenStream {
             fn inner(#params) -> optee_teec::Result<()> {
                 #f_block
             }
-            let mut inbuf = unsafe { std::slice::from_raw_parts_mut(data, in_len as usize) };
+            let mut inbuf = std::slice::from_raw_parts_mut(data, in_len as usize);
             let mut params = optee_teec::PluginParameters::new(cmd, sub_cmd, inbuf);
             if let Err(err) = inner(&mut params) {
                 return err.raw_code();
             };
             let outslice = params.get_out_slice();
-            unsafe {
-                *out_len = outslice.len() as u32;
-                std::ptr::copy(outslice.as_ptr(), data, outslice.len());
-            };
+            *out_len = outslice.len() as u32;
+            std::ptr::copy(outslice.as_ptr(), data, outslice.len());
             return optee_teec::raw::TEEC_SUCCESS;
         }
     )
diff --git a/optee-teec/optee-teec-sys/src/tee_client_api.rs b/optee-teec/optee-teec-sys/src/tee_client_api.rs
index 79ee42b..16b3d76 100644
--- a/optee-teec/optee-teec-sys/src/tee_client_api.rs
+++ b/optee-teec/optee-teec-sys/src/tee_client_api.rs
@@ -19,7 +19,7 @@ use libc::*;
 
 pub fn TEEC_PARAM_TYPES(p0:u32, p1:u32, p2:u32, p3:u32) -> u32 {
     let tmp = p1 << 4 | p2 << 8 | p3 << 12;
-    return p0 | tmp;
+    p0 | tmp
 }
 
 pub const TEEC_CONFIG_PAYLOAD_REF_COUNT: u32 = 4;
diff --git a/optee-teec/src/extension.rs b/optee-teec/src/extension.rs
index 206373a..c9887d4 100644
--- a/optee-teec/src/extension.rs
+++ b/optee-teec/src/extension.rs
@@ -24,7 +24,7 @@ pub struct PluginMethod {
     pub name: *const c_char,
     pub uuid: raw::TEEC_UUID,
     pub init: fn() -> raw::TEEC_Result,
-    pub invoke: fn(
+    pub invoke: unsafe fn(
         cmd: u32,
         sub_cmd: u32,
         data: *mut c_char,
@@ -51,7 +51,7 @@ impl<'a> PluginParameters<'a> {
             cmd,
             sub_cmd,
             inout,
-            outlen: 0 as usize,
+            outlen: 0_usize,
         }
     }
     pub fn set_buf_from_slice(&mut self, sendslice: &[u8]) -> Result<()> {
@@ -59,8 +59,8 @@ impl<'a> PluginParameters<'a> {
             println!("Overflow: Input length is less than output length");
             return Err(Error::new(ErrorKind::Security));
         }
-        self.outlen = sendslice.len() as usize;
-        self.inout[..self.outlen].copy_from_slice(&sendslice);
+        self.outlen = sendslice.len();
+        self.inout[..self.outlen].copy_from_slice(sendslice);
         Ok(())
     }
     pub fn get_out_slice(&self) -> &[u8] {
diff --git a/optee-teec/src/operation.rs b/optee-teec/src/operation.rs
index 985b954..2960182 100644
--- a/optee-teec/src/operation.rs
+++ b/optee-teec/src/operation.rs
@@ -40,7 +40,7 @@ impl<A: Param, B: Param, C: Param, D: Param> Operation<A, B, C, D> {
             p3.param_type(),
         )
         .into();
-        raw_op.params = [p0.into_raw(), p1.into_raw(), p2.into_raw(), p3.into_raw()];
+        raw_op.params = [p0.to_raw(), p1.to_raw(), p2.to_raw(), p3.to_raw()];
         Operation {
             raw: raw_op,
             phantom0: PhantomData,
diff --git a/optee-teec/src/parameter.rs b/optee-teec/src/parameter.rs
index 9712377..18bdd49 100644
--- a/optee-teec/src/parameter.rs
+++ b/optee-teec/src/parameter.rs
@@ -19,7 +19,7 @@ use crate::raw;
 use std::{marker, mem};
 
 pub trait Param {
-    fn into_raw(&mut self) -> raw::TEEC_Parameter;
+    fn to_raw(&mut self) -> raw::TEEC_Parameter;
     fn param_type(&self) -> ParamType;
     fn from_raw(raw: raw::TEEC_Parameter, param_type: ParamType) -> Self;
 }
@@ -53,14 +53,14 @@ impl ParamValue {
 }
 
 impl Param for ParamValue {
-    fn into_raw(&mut self) -> raw::TEEC_Parameter {
+    fn to_raw(&mut self) -> raw::TEEC_Parameter {
         raw::TEEC_Parameter { value: self.raw }
     }
 
     fn from_raw(raw: raw::TEEC_Parameter, param_type: ParamType) -> Self {
         Self {
             raw: unsafe { raw.value },
-            param_type: param_type,
+            param_type,
         }
     }
 
@@ -73,7 +73,7 @@ impl Param for ParamValue {
 pub struct ParamNone;
 
 impl Param for ParamNone {
-    fn into_raw(&mut self) -> raw::TEEC_Parameter {
+    fn to_raw(&mut self) -> raw::TEEC_Parameter {
         let raw: raw::TEEC_Parameter = unsafe { mem::zeroed() };
         raw
     }
@@ -133,7 +133,7 @@ impl<'a> ParamTmpRef<'a> {
 }
 
 impl<'a> Param for ParamTmpRef<'a> {
-    fn into_raw(&mut self) -> raw::TEEC_Parameter {
+    fn to_raw(&mut self) -> raw::TEEC_Parameter {
         raw::TEEC_Parameter { tmpref: self.raw }
     }
 
@@ -144,7 +144,7 @@ impl<'a> Param for ParamTmpRef<'a> {
     fn from_raw(raw: raw::TEEC_Parameter, param_type: ParamType) -> Self {
         Self {
             raw: unsafe { raw.tmpref },
-            param_type: param_type,
+            param_type,
             _marker: marker::PhantomData,
         }
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org