From f82ae0a78901c62644a53257d72fbc932d350ed7 Mon Sep 17 00:00:00 2001
From: chenmaodong <chenmaodong@huawei.com>
Date: Wed, 2 Jun 2021 17:16:56 +0800
Subject: [PATCH 6/6] fix use-after-free in cc_enclave_create The last
 parameter 'enclave' of cc_enclave_create will not be a double pointer, it'll
 be a single pointer now. Besides, the memory of parameter 'enclave' will
 malloc and free by users, you can check the example to find how to use it.

Signed-off-by: chenmaodong <chenmaodong@huawei.com>
---
 examples/helloworld/host/CMakeLists.txt       |  4 +-
 examples/helloworld/host/main.c               | 14 ++--
 examples/lrt/host/CMakeLists.txt              |  4 +-
 examples/lrt/host/main.c                      |  6 +-
 examples/seal_data/host/CMakeLists.txt        |  4 +-
 examples/seal_data/host/main.c                | 13 ++--
 examples/tls_enclave/host/main.c              |  6 +-
 inc/host_inc/enclave.h                        | 14 ++--
 inc/host_inc/enclave_internal.h               | 12 +--
 .../gp/itrustee/bottom_memory_check.c         | 17 +++-
 src/host_src/enclave.c                        | 78 +++++++------------
 src/host_src/enclave_internal.c               |  4 +-
 src/host_src/gp/gp_enclave.c                  | 18 ++---
 src/host_src/sgx/sgx_enclave.c                | 29 +++----
 tools/codegener/Genuntrust.ml                 | 21 ++++-
 tools/codegener/intel/CodeGen.ml              | 18 ++++-
 16 files changed, 144 insertions(+), 118 deletions(-)

diff --git a/examples/helloworld/host/CMakeLists.txt b/examples/helloworld/host/CMakeLists.txt
index 96985cb..3710954 100644
--- a/examples/helloworld/host/CMakeLists.txt
+++ b/examples/helloworld/host/CMakeLists.txt
@@ -63,9 +63,9 @@ if(CC_SGX)
 endif()
 
 if(CC_SIM)
-    target_link_libraries(${OUTPUT} secgearsim)
+    target_link_libraries(${OUTPUT} secgearsim pthread)
 else()
-    target_link_libraries(${OUTPUT} secgear)
+    target_link_libraries(${OUTPUT} secgear pthread)
 endif()
 set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE)
 
diff --git a/examples/helloworld/host/main.c b/examples/helloworld/host/main.c
index 7213a5e..a26fb6f 100644
--- a/examples/helloworld/host/main.c
+++ b/examples/helloworld/host/main.c
@@ -25,6 +25,10 @@ int main()
     char *path = PATH;
     char buf[BUF_LEN];
     cc_enclave_t *context = NULL;
+    context = (cc_enclave_t *)malloc(sizeof(cc_enclave_t));
+    if (!context) {
+        return CC_ERROR_OUT_OF_MEMORY;
+    }
     cc_enclave_result_t res;
 
     printf("Create secgear enclave\n");
@@ -43,7 +47,7 @@ int main()
 	    (void)strcat(real_p, "/enclave.signed.so");
     }
 
-    res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &context);
+    res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, context);
     if (res != CC_SUCCESS) {
         printf("Create enclave error\n");
         return res;
@@ -56,11 +60,9 @@ int main()
         printf("%s\n", buf);
     }
 
-    if (context != NULL) {
-        res = cc_enclave_destroy(context);
-        if(res != CC_SUCCESS) {
-            printf("Destroy enclave error\n");
-        }
+    res = cc_enclave_destroy(context);
+    if(res != CC_SUCCESS) {
+        printf("Destroy enclave error\n");
     }
     return res;
 }
diff --git a/examples/lrt/host/CMakeLists.txt b/examples/lrt/host/CMakeLists.txt
index 13f891a..1266384 100644
--- a/examples/lrt/host/CMakeLists.txt
+++ b/examples/lrt/host/CMakeLists.txt
@@ -62,9 +62,9 @@ if(CC_SGX)
 endif()
 
 if(CC_SIM)
-    target_link_libraries(${OUTPUT} secgearsim)
+    target_link_libraries(${OUTPUT} secgearsim pthread)
 else()
-    target_link_libraries(${OUTPUT} secgear)
+    target_link_libraries(${OUTPUT} secgear pthread)
 endif()
 set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE)
 
diff --git a/examples/lrt/host/main.c b/examples/lrt/host/main.c
index ba078c7..fd735d4 100644
--- a/examples/lrt/host/main.c
+++ b/examples/lrt/host/main.c
@@ -24,6 +24,10 @@ int main()
     char *path = PATH;
     char buf[BUF_LEN];
     cc_enclave_t *context = NULL;
+    context = (cc_enclave_t*)malloc(sizeof(cc_enclave_t));
+    if (!context) {
+        return CC_ERROR_OUT_OF_MEMORY;
+    }
     cc_enclave_result_t res;
 
     printf("Create secgear enclave\n");
@@ -42,7 +46,7 @@ int main()
 	    (void)strcat(real_p, "/enclave.signed.so");
     }
 
-    res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &context);
+    res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, context);
     if (res != CC_SUCCESS) {
         printf("Create enclave error\n");
         return res;
diff --git a/examples/seal_data/host/CMakeLists.txt b/examples/seal_data/host/CMakeLists.txt
index 19920b4..ef750b0 100644
--- a/examples/seal_data/host/CMakeLists.txt
+++ b/examples/seal_data/host/CMakeLists.txt
@@ -64,9 +64,9 @@ if(CC_SGX)
 endif()
 
 if(CC_SIM)
-    target_link_libraries(${OUTPUT} secgearsim)
+    target_link_libraries(${OUTPUT} secgearsim pthread)
 else()
-    target_link_libraries(${OUTPUT} secgear)
+    target_link_libraries(${OUTPUT} secgear pthread)
 endif()
 set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE)
 
diff --git a/examples/seal_data/host/main.c b/examples/seal_data/host/main.c
index ddfa253..9b1c4a6 100644
--- a/examples/seal_data/host/main.c
+++ b/examples/seal_data/host/main.c
@@ -22,8 +22,7 @@ int main()
     char *path = PATH;
     char buf[BUF_LEN];
     cc_enclave_result_t res;
-    cc_enclave_t *context = NULL;
-
+    cc_enclave_t context = {0};
     printf("Create secgear enclave\n");
     res = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &context);
     if (res != CC_SUCCESS) {
@@ -31,18 +30,16 @@ int main()
         return res;
     }
 
-    res = seal_data_test_func(context, &retval, buf, BUF_LEN);
+    res = seal_data_test_func(&context, &retval, buf, BUF_LEN);
     if (res != CC_SUCCESS || retval != (int)CC_SUCCESS) {
         printf("Ecall enclave error\n");
     } else {
         printf("%s\n", buf);
     }
 
-    if (context != NULL) {
-        res = cc_enclave_destroy(context);
-        if(res != CC_SUCCESS) {
-            printf("Destroy enclave error\n");
-        }
+    res = cc_enclave_destroy(&context);
+    if(res != CC_SUCCESS) {
+        printf("Destroy enclave error\n");
     }
     return res;
 }
diff --git a/examples/tls_enclave/host/main.c b/examples/tls_enclave/host/main.c
index 4407e64..c801558 100644
--- a/examples/tls_enclave/host/main.c
+++ b/examples/tls_enclave/host/main.c
@@ -126,6 +126,10 @@ int main(int argc, const char *argv[])
 {
     char *path = PATH;
     cc_enclave_t *context = NULL;
+    context = (cc_enclave_t*)malloc(sizeof(cc_enclave_t));
+    if (!context) {
+        return CC_ERROR_OUT_OF_MEMORY;
+    }
     struct sockaddr_in client_addr;
     socklen_t client_len;
     int server_fd = -1;
@@ -147,7 +151,7 @@ int main(int argc, const char *argv[])
         return CC_FAIL;
     }
     printf("Create secgear enclave\n");
-    res = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &context);
+    res = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, context);
     if (res != CC_SUCCESS) {
         printf("Create enclave error\n");
         goto end;
diff --git a/inc/host_inc/enclave.h b/inc/host_inc/enclave.h
index ca9e8da..1e3aefb 100644
--- a/inc/host_inc/enclave.h
+++ b/inc/host_inc/enclave.h
@@ -74,13 +74,13 @@ typedef struct _enclave {
  * hrough this attribute
  * */
 CC_API_SPEC cc_enclave_result_t cc_enclave_create(
-		const char *path, 
-		enclave_type_t type,
-		uint32_t version, 
-		uint32_t flags, 
-		const enclave_features_t *features, 
-		const uint32_t features_count,
-		cc_enclave_t  **enclave);
+                const char *path, 
+                enclave_type_t type,
+                uint32_t version, 
+                uint32_t flags, 
+                const enclave_features_t *features, 
+                const uint32_t features_count,
+                cc_enclave_t  *enclave);
 
 CC_API_SPEC cc_enclave_result_t cc_enclave_destroy(cc_enclave_t *context);
 
diff --git a/inc/host_inc/enclave_internal.h b/inc/host_inc/enclave_internal.h
index 771b7a3..5541557 100644
--- a/inc/host_inc/enclave_internal.h
+++ b/inc/host_inc/enclave_internal.h
@@ -33,9 +33,9 @@ typedef enum _enclave_state {
 /*the ops function structure is used to ecall, create, and destroy specific enclave*/
 struct cc_enclave_ops {
     cc_enclave_result_t (*cc_create_enclave)(
-		    cc_enclave_t **enclave, 
-		    const enclave_features_t *features,
-		    const uint32_t features_count);
+                    cc_enclave_t *enclave, 
+                    const enclave_features_t *features,
+                    const uint32_t features_count);
 
     cc_enclave_result_t (*cc_destroy_enclave)(cc_enclave_t *enclave);
 
@@ -83,12 +83,12 @@ typedef struct _list_ops_management {
 } list_ops_management;
 
 /*enclave engine register, unregister function*/
-typedef cc_enclave_result_t (*p_tee_registered)(cc_enclave_t **context, void *handle);
+typedef cc_enclave_result_t (*p_tee_registered)(cc_enclave_t *context, void *handle);
 typedef cc_enclave_result_t (*p_tee_unregistered)(cc_enclave_t *context, enclave_type_version_t type);
 
 
 /*creating enclave, first check in the list whether this engine has been added */
-uint32_t look_tee_in_list(enclave_type_version_t type, cc_enclave_t **);
+uint32_t look_tee_in_list(enclave_type_version_t type, cc_enclave_t *);
 
 enclave_type_version_t match_tee_type_version(enclave_type_t type, uint32_t version);
 
@@ -101,7 +101,7 @@ cc_enclave_result_t find_engine_registered(void *handle, p_tee_registered *p_fun
 
 ////////////////////////////////////////////////////////////////////////////////////////////
 /*each engine needs to implement registered, and the unregistered function declaration*/
-CC_API_SPEC cc_enclave_result_t cc_tee_registered(cc_enclave_t **context, void *handle);
+CC_API_SPEC cc_enclave_result_t cc_tee_registered(cc_enclave_t *context, void *handle);
 CC_API_SPEC cc_enclave_result_t cc_tee_unregistered(cc_enclave_t *context, enclave_type_version_t type_version);
 CC_API_SPEC void add_ops_list(struct list_ops_desc *node);
 CC_API_SPEC void remove_ops_list(const struct list_ops_desc *node);
diff --git a/src/enclave_src/gp/itrustee/bottom_memory_check.c b/src/enclave_src/gp/itrustee/bottom_memory_check.c
index 9b26c00..c32b2c3 100644
--- a/src/enclave_src/gp/itrustee/bottom_memory_check.c
+++ b/src/enclave_src/gp/itrustee/bottom_memory_check.c
@@ -12,6 +12,8 @@
 
 #include "bottom_memory_check.h"
 #include "tee_mem_mgmt_api.h"
+#include "tee_log.h"
+
 /* 
  * param buffer [IN] point to buffer address
  * param size   [IN] buffer size to be checked
@@ -21,7 +23,12 @@
  */
 bool itrustee_memory_in_enclave(const void *buffer, uint32_t size)
 {
-    return TEE_IsSecureMemory(buffer, size);
+    if (!TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, buffer, size)) {
+        return true;
+    } else if (!TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, buffer, size)) {
+        return true;
+    }
+    return false;
 }
 
 /*
@@ -31,8 +38,12 @@ bool itrustee_memory_in_enclave(const void *buffer, uint32_t size)
  * retval false target buffer is within enclave
  * retval true target buffer is outside of enclave
  */
-
 bool itrustee_memory_out_enclave(const void *buffer, uint32_t size)
 {
-    return !TEE_IsSecureMemory(buffer, size);
+    if (!TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, buffer, size) &&
+        !TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, buffer, size)) {
+        return false;
+    }
+    return true;
 }
+
diff --git a/src/host_src/enclave.c b/src/host_src/enclave.c
index 204c808..4b75b6e 100644
--- a/src/host_src/enclave.c
+++ b/src/host_src/enclave.c
@@ -34,9 +34,8 @@ static void check_dlopen_engine(p_tee_unregistered unregistered_func, cc_enclave
     pthread_mutex_unlock(&(g_list_ops.mutex_work));
 }
 
-
-static void error_handle(cc_enclave_t **l_context, void *handle, p_tee_registered registered_func,
-		p_tee_unregistered unregistered_func, cc_enclave_t ***enclave, char* path, bool check)
+static void error_handle(cc_enclave_t *l_context, void *handle, p_tee_registered registered_func,
+                         p_tee_unregistered unregistered_func, char* path, bool check)
 {
     cc_enclave_result_t tmp_res;
     if (check == true) {
@@ -46,19 +45,19 @@ static void error_handle(cc_enclave_t **l_context, void *handle, p_tee_registere
         pthread_mutex_unlock(&(g_list_ops.mutex_work));
     }
     /* in list find engine: handle is null and l_context is not null */
-    if (*l_context != NULL && (*l_context)->list_ops_node && !handle) {
-        tmp_res = find_engine_registered((*l_context)->list_ops_node->ops_desc->handle, NULL, &unregistered_func);
+    if (l_context != NULL && l_context->list_ops_node && !handle) {
+        tmp_res = find_engine_registered(l_context->list_ops_node->ops_desc->handle, NULL, &unregistered_func);
         if (tmp_res != CC_SUCCESS) {
             print_error_term("Can not find unregistered in the failed exit phase\n");
         } else {
-            check_dlopen_engine(unregistered_func, *l_context);
+            check_dlopen_engine(unregistered_func, l_context);
         }
     }
     /* handle is not null, means dlopen is ok */
     if (handle) {
         /* check if registered invoke success */
-        if ((*l_context) != NULL && registered_func && unregistered_func && (*l_context)->list_ops_node) {
-            check_dlopen_engine(unregistered_func,*l_context);
+        if (l_context != NULL && registered_func && unregistered_func && l_context->list_ops_node) {
+            check_dlopen_engine(unregistered_func, l_context);
         } else {
             /* means registered func invoke fail OR find_engine_registered fail */
             dlclose(handle);
@@ -67,14 +66,6 @@ static void error_handle(cc_enclave_t **l_context, void *handle, p_tee_registere
     if (path) {
         free(path);
     }
-
-    if (*l_context) {
-        free(*l_context);
-    }
-    *l_context = NULL;
-    if (*enclave != NULL) {
-    	**enclave = NULL;
-    }
 }
 
 /* Lock to check the number of enclave
@@ -107,9 +98,9 @@ done:
  *  uses the currently unsupported bit. the simulation feature and the debug mode only supports sgx
  */
 static bool check_flag(cc_enclave_result_t *res, const char *path, uint32_t flags, const enclave_features_t *features,
-    const uint32_t features_count, cc_enclave_t **enclave)
+    const uint32_t features_count, cc_enclave_t *enclave)
 {
-    if (enclave == NULL || (*enclave != NULL && (*enclave)->used_flag == true)) {
+    if (enclave == NULL || (enclave != NULL && enclave->used_flag == true)) {
         *res = CC_ERROR_INVALID_ENCLAVE_ID;
         return false;
     }
@@ -140,18 +131,6 @@ static bool chose_engine_type(cc_enclave_result_t *res, enclave_type_t type, uin
     return true;
 }
 
-static bool allocate_context_memory(cc_enclave_result_t *res, cc_enclave_t **l_context)
-{
-    *l_context = (cc_enclave_t *)malloc(sizeof(cc_enclave_t));
-    if (*l_context == NULL) {
-        *res = CC_ERROR_OUT_OF_MEMORY;
-        print_error_term("Memory out \n");
-        return false;
-    }
-    memset(*l_context, 0, sizeof(cc_enclave_t));
-    return true;
-}
-
 /* check and transform enclave paths */
 static bool check_transform_path(cc_enclave_result_t *res, const char *path, char **l_path)
 {
@@ -182,7 +161,7 @@ static bool check_transform_path(cc_enclave_result_t *res, const char *path, cha
 
 /* The enclave variable is the output context when successfully created */
 cc_enclave_result_t cc_enclave_create(const char *path, enclave_type_t type, uint32_t version, uint32_t flags,
-    const enclave_features_t *features, const uint32_t features_count, cc_enclave_t **enclave)
+    const enclave_features_t *features, const uint32_t features_count, cc_enclave_t *enclave)
 {
     int32_t  ires   = 0;
     uint32_t uires  = 0;
@@ -191,7 +170,6 @@ cc_enclave_result_t cc_enclave_create(const char *path, enclave_type_t type, uin
     char *l_path     = NULL;
 
     cc_enclave_result_t res;
-    cc_enclave_t *l_context = NULL;
     enclave_type_version_t type_version;
 
     p_tee_registered   registered_func  = NULL;
@@ -208,8 +186,8 @@ cc_enclave_result_t cc_enclave_create(const char *path, enclave_type_t type, uin
         return res;
     }
 
-    if (!check_transform_path(&res, path, &l_path) || !chose_engine_type(&res, type, version, &type_version)
-    || !allocate_context_memory(&res, &l_context)) {
+    memset(enclave, 0, sizeof(cc_enclave_t));
+    if (!check_transform_path(&res, path, &l_path) || !chose_engine_type(&res, type, version, &type_version)) {
         goto done;
     }
 
@@ -220,11 +198,11 @@ cc_enclave_result_t cc_enclave_create(const char *path, enclave_type_t type, uin
     
     /* initialize the context */
 
-    pthread_rwlock_init(&(l_context->rwlock), NULL);
-    l_context->path  = l_path;
-    l_context->flags = flags;
-    l_context->type  = type_version;
-    l_context->used_flag = true;
+    pthread_rwlock_init(&(enclave->rwlock), NULL);
+    enclave->path  = l_path;
+    enclave->flags = flags;
+    enclave->type  = type_version;
+    enclave->used_flag = true;
 
     /* if an enclave is created multiple times, first find it in the global list,
      * maybe the information about this engine has been filled in the list 
@@ -232,7 +210,7 @@ cc_enclave_result_t cc_enclave_create(const char *path, enclave_type_t type, uin
     ires = pthread_mutex_lock(&(g_list_ops.mutex_work));
     SECGEAR_CHECK_MUTEX_RES_CC(ires, res);
     if (g_list_ops.count > 0) {
-        uires = look_tee_in_list(type_version, &l_context);
+        uires = look_tee_in_list(type_version, enclave);
     }
     ires = pthread_mutex_unlock(&(g_list_ops.mutex_work));
     SECGEAR_CHECK_MUTEX_RES_CC(ires, res);
@@ -252,7 +230,7 @@ cc_enclave_result_t cc_enclave_create(const char *path, enclave_type_t type, uin
         res = find_engine_registered(handle, &registered_func, &unregistered_func);
         SECGEAR_CHECK_RES_UNLOCK(res);
 
-        res = (*registered_func)(&l_context, handle);
+        res = (*registered_func)(enclave, handle);
         SECGEAR_CHECK_RES_UNLOCK(res);
 
         ires = pthread_mutex_unlock(&(g_list_ops.mutex_work));
@@ -260,10 +238,9 @@ cc_enclave_result_t cc_enclave_create(const char *path, enclave_type_t type, uin
     }
 
     /* call the registered function of each engine */
-    *enclave = l_context;
-    if (l_context->list_ops_node != NULL && l_context->list_ops_node->ops_desc->ops->cc_create_enclave != NULL) {
+    if (enclave->list_ops_node != NULL && enclave->list_ops_node->ops_desc->ops->cc_create_enclave != NULL) {
         /* failure of this function will not bring out additional memory that needs to be managed */
-        res = l_context->list_ops_node->ops_desc->ops->cc_create_enclave(enclave, features, features_count);
+        res = enclave->list_ops_node->ops_desc->ops->cc_create_enclave(enclave, features, features_count);
         SECGEAR_CHECK_RES(res);
     } else {
         print_error_goto("Enclave type version %d no valid ops function", type_version);
@@ -271,11 +248,10 @@ cc_enclave_result_t cc_enclave_create(const char *path, enclave_type_t type, uin
 
     return CC_SUCCESS;
 done:
-    error_handle(&l_context, handle, registered_func, unregistered_func, &enclave, l_path, check);
+    error_handle(enclave, handle, registered_func, unregistered_func, l_path, check);
     return res;
 }
 
-
 cc_enclave_result_t cc_enclave_destroy(cc_enclave_t *context)
 {
     int32_t ires = 0;
@@ -289,7 +265,10 @@ cc_enclave_result_t cc_enclave_destroy(cc_enclave_t *context)
         return CC_ERROR_BAD_PARAMETERS;
     }
 
-    pthread_rwlock_wrlock(&(context->rwlock));
+    ires = pthread_rwlock_wrlock(&(context->rwlock));
+    if (ires) {
+        return CC_ERROR_BUSY;
+    }
     if (context->list_ops_node->ops_desc->ops->cc_destroy_enclave != NULL) {
         res = context->list_ops_node->ops_desc->ops->cc_destroy_enclave(context);
         SECGEAR_CHECK_RES(res);
@@ -302,7 +281,7 @@ cc_enclave_result_t cc_enclave_destroy(cc_enclave_t *context)
     SECGEAR_CHECK_RES(res);
 
     /* lock call unregistered func */
-    pthread_mutex_lock(&(g_list_ops.mutex_work));
+    ires = pthread_mutex_lock(&(g_list_ops.mutex_work));
     SECGEAR_CHECK_MUTEX_RES_CC(ires, res);
     /* call enclave engine free node */
     res = (*unregistered_funcc)(context, context->list_ops_node->ops_desc->type_version);
@@ -318,7 +297,7 @@ cc_enclave_result_t cc_enclave_destroy(cc_enclave_t *context)
     }
     /* free enclave number resources */
     g_list_ops.enclaveState.enclave_count--;
-    pthread_mutex_unlock(&(g_list_ops.mutex_work));
+    ires = pthread_mutex_unlock(&(g_list_ops.mutex_work));
     SECGEAR_CHECK_MUTEX_RES_CC(ires, res);
 
     res = CC_SUCCESS;
@@ -330,7 +309,6 @@ done:
         pthread_rwlock_unlock(&context->rwlock);
         pthread_rwlock_destroy(&context->rwlock);
         explicit_bzero(context, sizeof(cc_enclave_t));
-        free(context);
     }
     return res;
 }
diff --git a/src/host_src/enclave_internal.c b/src/host_src/enclave_internal.c
index 962fc07..b30a207 100644
--- a/src/host_src/enclave_internal.c
+++ b/src/host_src/enclave_internal.c
@@ -318,7 +318,7 @@ enclave_type_version_t match_tee_type_version(enclave_type_t type, uint32_t vers
 /* find return 1， otherwise 0
  * Lock: prevent it from being intercepted by other insertion
  * operations when searching, not in this function, but in the calling function */
-uint32_t look_tee_in_list(enclave_type_version_t type, cc_enclave_t **context)
+uint32_t look_tee_in_list(enclave_type_version_t type, cc_enclave_t *context)
 {
     uint32_t res = 0;
     struct list_ops_desc *p = g_list_ops.list_head;
@@ -328,7 +328,7 @@ uint32_t look_tee_in_list(enclave_type_version_t type, cc_enclave_t **context)
             /* this enclave ref +1 */
             ++(p->ops_desc->count);
             /* Assign the found node to the context */
-            (*context)->list_ops_node = p;
+            context->list_ops_node = p;
             break;
         }
         p = p->next;
diff --git a/src/host_src/gp/gp_enclave.c b/src/host_src/gp/gp_enclave.c
index 86ea941..c7554de 100644
--- a/src/host_src/gp/gp_enclave.c
+++ b/src/host_src/gp/gp_enclave.c
@@ -343,13 +343,13 @@ cleanup:
 }
 
 /* itrustee enclave engine create func */
-cc_enclave_result_t _gp_create(cc_enclave_t  **enclave,
+cc_enclave_result_t _gp_create(cc_enclave_t  *enclave,
     const enclave_features_t *features, const uint32_t features_count)
 {
     TEEC_Result result_tee;
     cc_enclave_result_t result_cc;
 
-    if (!*enclave) {
+    if (!enclave) {
         print_error_term("Context parameter error\n");
         return CC_ERROR_BAD_PARAMETERS;
     }
@@ -361,7 +361,7 @@ cc_enclave_result_t _gp_create(cc_enclave_t  **enclave,
     }
 
     gp_context_t *gp_context = NULL;
-    result_cc = malloc_and_init_context(&gp_context, (*enclave)->path, (*enclave)->type);
+    result_cc = malloc_and_init_context(&gp_context, enclave->path, enclave->type);
     if (result_cc != CC_SUCCESS) {
         return result_cc;
     }
@@ -372,18 +372,18 @@ cc_enclave_result_t _gp_create(cc_enclave_t  **enclave,
     operation.started = 1;
     operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT);
 
-    (gp_context->ctx).ta_path = (uint8_t*)(*enclave)->path;
+    (gp_context->ctx).ta_path = (uint8_t*)enclave->path;
 
     uint32_t origin;
     result_tee = TEEC_OpenSession(&(gp_context->ctx), &(gp_context->session), &gp_context->uuid,
         TEEC_LOGIN_IDENTIFY, NULL, &operation, &origin);
     if (result_tee != TEEC_SUCCESS) {
-        result_cc = conversion_res_status(result_tee, (*enclave)->type);
+        result_cc = conversion_res_status(result_tee, enclave->type);
         print_error_term("TEEC open session failed\n");
         goto cleanup;
     }
     print_debug("TEEC open session success\n");
-    (*enclave)->private_data = (void *)gp_context;
+    enclave->private_data = (void *)gp_context;
     return CC_SUCCESS;
 cleanup:
     TEEC_FinalizeContext(&(gp_context->ctx));
@@ -606,17 +606,17 @@ struct list_ops_desc g_node = {
 #define OPS_STRU g_ops
 
 /* enclave engine registered */
-cc_enclave_result_t cc_tee_registered(cc_enclave_t **context, void *handle)
+cc_enclave_result_t cc_tee_registered(cc_enclave_t *context, void *handle)
 {
     /* 1 check enclave type; 2-4 check node fill */
     size_t len = strlen(OPS_NAME.name);
-    if (OPS_NAME.type_version != (*context)->type || OPS_NODE.ops_desc != &OPS_NAME ||
+    if (OPS_NAME.type_version != context->type || OPS_NODE.ops_desc != &OPS_NAME ||
         len >= MAX_ENGINE_NAME_LEN || OPS_NAME.ops != &OPS_STRU) {
         print_error_goto("The struct cc_enclave_ops_desc initialization error\n");
     }
 
     OPS_NAME.handle = handle;
-    (*context)->list_ops_node = &OPS_NODE;
+    context->list_ops_node = &OPS_NODE;
     add_ops_list(&OPS_NODE);
     return  CC_SUCCESS;
 done:
diff --git a/src/host_src/sgx/sgx_enclave.c b/src/host_src/sgx/sgx_enclave.c
index 258c58a..aa26957 100644
--- a/src/host_src/sgx/sgx_enclave.c
+++ b/src/host_src/sgx/sgx_enclave.c
@@ -70,7 +70,8 @@ cc_enclave_result_t conversion_res_status(uint32_t enclave_res, enclave_type_ver
     }
 }
 
-cc_enclave_result_t _sgx_create_with_features(cc_enclave_t **enclave, const enclave_features_t *features, sgx_context_t **l_context)
+cc_enclave_result_t _sgx_create_with_features(cc_enclave_t *enclave, const enclave_features_t *features,
+                                              sgx_context_t *l_context)
 {
     cc_enclave_result_t res;
     sgx_status_t sgx_res;
@@ -90,8 +91,8 @@ cc_enclave_result_t _sgx_create_with_features(cc_enclave_t **enclave, const encl
         l_config.num_uworkers = l_switch->host_worker;
 
         enclave_ex_p[SGX_CREATE_ENCLAVE_EX_SWITCHLESS_BIT_IDX] = (const void *)&l_config;
-        sgx_res = sgx_create_enclave_ex((*enclave)->path, (uint32_t)((*enclave)->flags & SECGEAR_DEBUG_FLAG), NULL,
-            NULL, &((*l_context)->edi), NULL, SGX_CREATE_ENCLAVE_EX_SWITCHLESS, enclave_ex_p);
+        sgx_res = sgx_create_enclave_ex(enclave->path, (uint32_t)(enclave->flags & SECGEAR_DEBUG_FLAG), NULL,
+            NULL, &(l_context->edi), NULL, SGX_CREATE_ENCLAVE_EX_SWITCHLESS, enclave_ex_p);
     } else if (features->setting_type & _CESGX_PROTECTED_CODE_LOADER_FEATURES) {
         /* For the Sealing Enclave and the IP Enclave to be able to seal and unseal the
         decryption key, both enclaves must be signed with the same Intel SGX ISV
@@ -100,14 +101,14 @@ cc_enclave_result_t _sgx_create_with_features(cc_enclave_t **enclave, const encl
         l_plc = (cesgx_plc_config_t *)features->feature_desc;
         SECGEAR_CHECK_SIZE(l_plc->len);
         SECGEAR_CHECK_CHAR(l_plc->path);
-        sgx_res = sgx_create_encrypted_enclave((*enclave)->path, (uint32_t)((*enclave)->flags & SECGEAR_DEBUG_FLAG), NULL,
-                                                  NULL, &((*l_context)->edi), NULL, (uint8_t *)l_plc->path);
+        sgx_res = sgx_create_encrypted_enclave(enclave->path, (uint32_t)(enclave->flags & SECGEAR_DEBUG_FLAG), NULL,
+                                                  NULL, &(l_context->edi), NULL, (uint8_t *)l_plc->path);
     } else {
         res = CC_ERROR_BAD_STATE;
         print_error_goto("The set feature is currently not supported\n");
     }
     if (sgx_res != SGX_SUCCESS) {
-        res = conversion_res_status(sgx_res, (*enclave)->type);
+        res = conversion_res_status(sgx_res, enclave->type);
         print_error_goto("Failed to create sgx enclave %s\n",cc_enclave_res2_str(res));
     }
     res = CC_SUCCESS;
@@ -115,7 +116,7 @@ done:
     return res;
 }
 
-cc_enclave_result_t _sgx_create(cc_enclave_t **enclave, const enclave_features_t *features,
+cc_enclave_result_t _sgx_create(cc_enclave_t *enclave, const enclave_features_t *features,
                                   const uint32_t features_count)
 {
     cc_enclave_result_t res = CC_ERROR_UNEXPECTED;
@@ -129,15 +130,15 @@ cc_enclave_result_t _sgx_create(cc_enclave_t **enclave, const enclave_features_t
     }
     switch (features_count) {
         case 0:
-            sgx_res = sgx_create_enclave((*enclave)->path, (uint32_t)((*enclave)->flags & SECGEAR_DEBUG_FLAG), NULL,
+            sgx_res = sgx_create_enclave(enclave->path, (uint32_t)(enclave->flags & SECGEAR_DEBUG_FLAG), NULL,
                     NULL, &(l_context->edi), NULL);
             if (sgx_res != SGX_SUCCESS) {
-                res = conversion_res_status(sgx_res, (*enclave)->type);
+                res = conversion_res_status(sgx_res, enclave->type);
                 print_error_goto("Failed to create sgx enclave\n");
             }
             break;
         case 1:
-            res = _sgx_create_with_features(enclave, features,  &l_context);
+            res = _sgx_create_with_features(enclave, features, l_context);
             if (res != CC_SUCCESS) {
                 goto done;
             }
@@ -146,7 +147,7 @@ cc_enclave_result_t _sgx_create(cc_enclave_t **enclave, const enclave_features_t
             res = CC_ERROR_BAD_STATE;
             print_error_goto("SGX currently does not support setting features\n");
     }
-    (*enclave)->private_data = (void *)l_context;
+    enclave->private_data = (void *)l_context;
     return CC_SUCCESS;
 done:
     if (l_context) {
@@ -229,15 +230,15 @@ struct list_ops_desc sgx_ops_node = {
 #define OPS_NODE sgx_ops_node
 #define OPS_STRU sgx_ops
  
-cc_enclave_result_t cc_tee_registered(cc_enclave_t **context, void *handle)
+cc_enclave_result_t cc_tee_registered(cc_enclave_t *context, void *handle)
 {
     size_t len = strlen(OPS_NAME.name);
-    if (OPS_NAME.type_version != (*context)->type || OPS_NODE.ops_desc != &OPS_NAME ||
+    if (OPS_NAME.type_version != context->type || OPS_NODE.ops_desc != &OPS_NAME ||
         len >= MAX_ENGINE_NAME_LEN || OPS_NAME.ops != &OPS_STRU) {
         print_error_goto("The struct cc_enclave_ops_desc initialization error\n");
     }
     OPS_NAME.handle = handle;
-    (*context)->list_ops_node = &OPS_NODE;
+    context->list_ops_node = &OPS_NODE;
     add_ops_list(&OPS_NODE);
     return  CC_SUCCESS;
 done:
diff --git a/tools/codegener/Genuntrust.ml b/tools/codegener/Genuntrust.ml
index 8edbc8b..7171ef2 100644
--- a/tools/codegener/Genuntrust.ml
+++ b/tools/codegener/Genuntrust.ml
@@ -49,6 +49,20 @@ let get_param_count (pt: parameter_type) =
 let set_call_user_func (fd : func_decl) = 
     [
         "/* Call the cc_enclave function */";
+        "if (!enclave) {";
+        "    ret = CC_ERROR_BAD_PARAMETERS;";
+        "    goto exit;";
+        "}";
+        "if (pthread_rwlock_rdlock(&enclave->rwlock)) {";
+        "    ret = CC_ERROR_BUSY;";
+        "    goto exit;";
+        "}";
+        "if (!enclave->list_ops_node || !enclave->list_ops_node->ops_desc ||";
+        "         !enclave->list_ops_node->ops_desc->ops ||";
+        "         !enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave) {";
+        "    ret = CC_ERROR_BAD_PARAMETERS;";
+        "    goto exit;";
+        "}";
         "if ((ret = enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave(";
         "         enclave,";
         sprintf "         fid_%s," fd.fname;
@@ -57,8 +71,13 @@ let set_call_user_func (fd : func_decl) =
         "         out_buf,";
         "         out_buf_size,";
         "         &ms,";
-        "         &ocall_table)) != CC_SUCCESS)";
+        "         &ocall_table)) != CC_SUCCESS) {";
+        "    pthread_rwlock_unlock(&enclave->rwlock);";
+        "    goto exit; }";
+        "if (pthread_rwlock_unlock(&enclave->rwlock)) {";
+        "    ret = CC_ERROR_BUSY;";
         "    goto exit;";
+        "}";
     ]
 
 let set_ecall_func_arguments (fd : func_decl) =
diff --git a/tools/codegener/intel/CodeGen.ml b/tools/codegener/intel/CodeGen.ml
index d9ccf7c..6fb05fb 100644
--- a/tools/codegener/intel/CodeGen.ml
+++ b/tools/codegener/intel/CodeGen.ml
@@ -872,7 +872,11 @@ let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) =
   let sgx_ecall_fn = get_sgx_fname SGX_ECALL tf.Ast.tf_is_switchless in
 
   (* Normal case - do ECALL with marshaling structure*)
-  let ecall_with_ms = sprintf "if(!enclave || !enclave->list_ops_node || !enclave->list_ops_node->ops_desc ||\n\
+  let ecall_with_ms = sprintf "if(!enclave) \n\
+                    \t\treturn CC_ERROR_BAD_PARAMETERS;
+        if (pthread_rwlock_rdlock(&enclave->rwlock))\n\
+                    \t\treturn CC_ERROR_BUSY;
+        if (!enclave->list_ops_node || !enclave->list_ops_node->ops_desc ||\n\
                     \t\t!enclave->list_ops_node->ops_desc->ops || \n\
                     \t\t!enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave)\n\
                     \t\treturn CC_ERROR_BAD_PARAMETERS;
@@ -884,12 +888,17 @@ let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) =
                     \t\tNULL,\n\
                     \t\t0,\n\
                     \t\t&%s,\n\
-                    \t\t%s);\n" idx  ms_struct_val ocall_table_ptr in
+                    \t\t%s);
+        pthread_rwlock_unlock(&enclave->rwlock);\n" idx  ms_struct_val ocall_table_ptr in
 
   (* Rare case - the trusted function doesn't have parameter nor return value.
    * In this situation, no marshaling structure is required - passing in NULL.
    *)
-  let ecall_null = sprintf "if(!enclave || !enclave->list_ops_node || !enclave->list_ops_node->ops_desc ||\n\
+  let ecall_null = sprintf "if(!enclave) \n\
+                    \t\treturn CC_ERROR_BAD_PARAMETERS;
+        if (pthread_rwlock_rdlock(&enclave->rwlock))\n\
+                    \t\treturn CC_ERROR_BUSY;
+        if(!enclave || !enclave->list_ops_node || !enclave->list_ops_node->ops_desc ||\n\
                     \t\t!enclave->list_ops_node->ops_desc->ops || \n\
                     \t\t!enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave)\n\
                     \t\treturn CC_ERROR_BAD_PARAMETERS;
@@ -901,7 +910,8 @@ let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) =
                     \t\tNULL,\n\
                     \t\t0,\n\
                     \t\tNULL,\n\
-                    \t\t%s);\n" idx ocall_table_ptr
+                    \t\t%s);
+        pthread_rwlock_unlock(&enclave->rwlock);\n" idx ocall_table_ptr
   in
   let update_retval = sprintf "if (result == CC_SUCCESS && %s) *%s = %s.%s;"
                               retval_name retval_name ms_struct_val ms_retval_name in
-- 
2.27.0

