1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12
13 #include "tee_operation.h"
14 #include <dlist.h>
15 #include <tee_log.h>
16 #include <pthread.h>
17 #include <errno.h>
18
19 #define LOCK_UNLOCK_OK 0
20 static dlist_head(g_operation_list);
21 static pthread_mutex_t g_operation_mutex = PTHREAD_MUTEX_INITIALIZER;
22
23 typedef struct {
24 struct dlist_node list_node;
25 TEE_OperationHandle operation;
26 } operation_node;
27
operation_lock_ops(pthread_mutex_t * mtx)28 static int32_t operation_lock_ops(pthread_mutex_t *mtx)
29 {
30 int32_t ret = pthread_mutex_lock(mtx);
31 if (ret == EOWNERDEAD) /* owner died, use consistent to recover and lock the mutex */
32 return pthread_mutex_consistent(mtx);
33
34 return ret;
35 }
36
add_operation(TEE_OperationHandle operation)37 TEE_Result add_operation(TEE_OperationHandle operation)
38 {
39 if (operation == NULL) {
40 tloge("The operation is NULL\n");
41 return TEE_ERROR_BAD_PARAMETERS;
42 }
43
44 operation_node *valid_operation = TEE_Malloc(sizeof(*valid_operation), TEE_MALLOC_FILL_ZERO);
45 if (valid_operation == NULL) {
46 tloge("Malloc operation node failed\n");
47 return TEE_ERROR_OUT_OF_MEMORY;
48 }
49 valid_operation->operation = operation;
50
51 if (operation_lock_ops(&g_operation_mutex) != LOCK_UNLOCK_OK) {
52 tloge("Lock operation mutex failed\n");
53 TEE_Free(valid_operation);
54 return TEE_ERROR_GENERIC;
55 }
56 dlist_insert_head(&(valid_operation->list_node), &g_operation_list);
57 if (pthread_mutex_unlock(&g_operation_mutex) != LOCK_UNLOCK_OK) {
58 tloge("Unlock operation mutex failed\n");
59 dlist_delete(&(valid_operation->list_node));
60 TEE_Free(valid_operation);
61 return TEE_ERROR_GENERIC;
62 }
63
64 return TEE_SUCCESS;
65 }
66
delete_operation(const TEE_OperationHandle operation)67 void delete_operation(const TEE_OperationHandle operation)
68 {
69 if (operation == NULL)
70 return;
71
72 operation_node *valid_operation = NULL;
73 operation_node *tmp = NULL;
74
75 if (operation_lock_ops(&g_operation_mutex) != LOCK_UNLOCK_OK) {
76 tloge("Lock operation mutex failed\n");
77 return;
78 }
79
80 dlist_for_each_entry_safe(valid_operation, tmp, &g_operation_list, operation_node, list_node) {
81 if (valid_operation->operation == operation) {
82 dlist_delete(&(valid_operation->list_node));
83 TEE_Free(valid_operation);
84 valid_operation = NULL;
85 break;
86 }
87 }
88 if (pthread_mutex_unlock(&g_operation_mutex) != LOCK_UNLOCK_OK) {
89 tloge("Unlock operation mutex failed\n");
90 return;
91 }
92
93 return;
94 }
95
check_operation(const TEE_OperationHandle operation)96 TEE_Result check_operation(const TEE_OperationHandle operation)
97 {
98 TEE_Result ret = TEE_ERROR_GENERIC;
99 operation_node *valid_operation = NULL;
100
101 if (operation == NULL)
102 return TEE_ERROR_BAD_PARAMETERS;
103
104 if (operation_lock_ops(&g_operation_mutex) != LOCK_UNLOCK_OK) {
105 tloge("Lock operation mutex failed\n");
106 return TEE_ERROR_GENERIC;
107 }
108
109 dlist_for_each_entry(valid_operation, &g_operation_list, operation_node, list_node) {
110 if (valid_operation->operation == operation) {
111 ret = TEE_SUCCESS;
112 break;
113 }
114 }
115
116 if (pthread_mutex_unlock(&g_operation_mutex) != LOCK_UNLOCK_OK) {
117 tloge("Unlock operation mutex failed\n");
118 return TEE_ERROR_GENERIC;
119 }
120
121 return ret;
122 }
123