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 #include "drv_fd_ops.h"
13 #include <securec.h>
14 #include <dlist.h>
15 #include <tee_log.h>
16 #include <tee_drv_internal.h>
17 #include "drv_ipc_mgr.h"
18 #include "task_mgr.h"
19
drv_mutex_lock(pthread_mutex_t * mtx)20 int32_t drv_mutex_lock(pthread_mutex_t *mtx)
21 {
22 if (mtx == NULL)
23 return -1;
24
25 int32_t ret = pthread_mutex_lock(mtx);
26
27 return ret;
28 }
29
drv_mutex_init(pthread_mutex_t * mtx)30 int32_t drv_mutex_init(pthread_mutex_t *mtx)
31 {
32 int32_t ret;
33
34 if (mtx == NULL) {
35 tloge("invalid mtx\n");
36 return -1;
37 }
38
39 ret = pthread_mutex_init(mtx, NULL);
40 if (ret != 0) {
41 tloge("pthread mutex init failed with ret:%d\n", ret);
42 }
43
44 return ret;
45 }
46
alloc_and_init_fd_node(void)47 struct fd_node *alloc_and_init_fd_node(void)
48 {
49 struct fd_node *data = malloc(sizeof(*data));
50 if (data == NULL) {
51 tloge("alloc fd data fail\n");
52 return NULL;
53 }
54
55 (void)memset_s(data, sizeof(*data), 0, sizeof(*data));
56
57 dlist_init(&data->data_list);
58 data->fd = -1;
59 data->drv = NULL;
60 data->close_flag = false;
61
62 return data;
63 }
64
add_fd_to_drvcall_node(struct fd_node * data,struct task_node * node)65 int32_t add_fd_to_drvcall_node(struct fd_node *data, struct task_node *node)
66 {
67 if (data == NULL || node == NULL) {
68 tloge("insert fd invalid param\n");
69 return -1;
70 }
71
72 int32_t ret = drv_mutex_lock(&node->fd_mtx);
73 if (ret != 0) {
74 tloge("lock fd mtx fail\n");
75 return -1;
76 }
77
78 dlist_insert_tail(&data->data_list, &node->fd_head);
79
80 ret = pthread_mutex_unlock(&node->fd_mtx);
81 if (ret != 0)
82 tloge("something wrong, unlock fd mtx fail\n");
83
84 return 0;
85 }
86
close_get_fd_node_with_lock(struct task_node * node,int64_t fd)87 struct fd_node *close_get_fd_node_with_lock(struct task_node *node, int64_t fd)
88 {
89 struct fd_node *data = NULL;
90
91 if (node == NULL) {
92 tloge("invalid drvcall node\n");
93 return NULL;
94 }
95
96 int32_t ret = drv_mutex_lock(&node->fd_mtx);
97 if (ret != 0) {
98 tloge("get lock fd mtx fail\n");
99 return NULL;
100 }
101
102 struct dlist_node *pos = NULL;
103 struct dlist_node *next = NULL;
104 struct fd_node *temp = NULL;
105 dlist_for_each_safe(pos, next, &node->fd_head) {
106 temp = dlist_entry(pos, struct fd_node, data_list);
107 if (temp->fd == fd) {
108 if (temp->close_flag) {
109 tloge("this fd:0x%llx has already close\n", fd);
110 break;
111 }
112
113 data = temp;
114 data->close_flag = true;
115 }
116 }
117
118 ret = pthread_mutex_unlock(&node->fd_mtx);
119 if (ret != 0)
120 tloge("something wrong, get fd unlock fd mtx fail\n");
121
122 return data;
123 }
124
del_fd_to_drvcall_node(struct fd_node ** fnode,struct task_node * node)125 int32_t del_fd_to_drvcall_node(struct fd_node **fnode, struct task_node *node)
126 {
127 if (fnode == NULL || node == NULL || *fnode == NULL) {
128 tloge("put fd invalid param\n");
129 return -1;
130 }
131
132 struct fd_node *data = *fnode;
133
134 int32_t ret = drv_mutex_lock(&node->fd_mtx);
135 if (ret != 0) {
136 tloge("lock fd mtx fail\n");
137 return -1;
138 }
139
140 if (node->fd_count > 0)
141 node->fd_count--;
142 else
143 tloge("something wrong, task:0x%x fd_count is zero\n", node->pid);
144
145 dlist_delete(&data->data_list);
146
147 ret = pthread_mutex_unlock(&node->fd_mtx);
148 if (ret != 0)
149 tloge("something wrong, unlock fd mtx fail\n");
150
151 free(data);
152 *fnode = NULL;
153
154 return 0;
155 }
156
dump_fd_node(const struct task_node * node)157 static void dump_fd_node(const struct task_node *node)
158 {
159 struct dlist_node *pos = NULL;
160 struct dlist_node *next = NULL;
161 struct fd_node *temp = NULL;
162
163 dlist_for_each_safe(pos, next, &node->fd_head) {
164 temp = dlist_entry(pos, struct fd_node, data_list);
165 tlogi("\t fd:0x%llx close_flag:%d ", temp->fd, (int32_t)temp->close_flag);
166 if (temp->drv != NULL && temp->drv->tlv.drv_conf != NULL)
167 tlogi("\t\t drv_name:%s\n", temp->drv->tlv.drv_conf->mani.service_name);
168 else
169 tloge("\t\t fd no driver (something wrong)\n");
170 }
171 }
172
get_fd_count(struct task_node * node)173 int32_t get_fd_count(struct task_node *node)
174 {
175 if (node == NULL) {
176 tloge("get fd count invalid param\n");
177 return -1;
178 }
179
180 int32_t func_ret = -1;
181 int32_t ret = drv_mutex_lock(&node->fd_mtx);
182 if (ret != 0) {
183 tloge("get fd count lock fd mtx fail\n");
184 return -1;
185 }
186
187 if (node->fd_count >= TASK_FD_COUNT_MAX) {
188 tloge("task:%u fd_count:%u is overflow\n", node->pid, node->fd_count);
189 dump_fd_node(node);
190 } else {
191 node->fd_count++;
192 func_ret = 0;
193 }
194
195 ret = pthread_mutex_unlock(&node->fd_mtx);
196 if (ret != 0)
197 tloge("something wrong, get fd count unlock fd mtx fail\n");
198
199 return func_ret;
200 }
201
put_fd_count(struct task_node * node)202 void put_fd_count(struct task_node *node)
203 {
204 if (node == NULL) {
205 tloge("put fd count invalid param\n");
206 return;
207 }
208
209 int32_t ret = drv_mutex_lock(&node->fd_mtx);
210 if (ret != 0) {
211 tloge("put fd count lock fd mtx fail\n");
212 return;
213 }
214
215 if (node->fd_count == 0)
216 tloge("something wrong, task:%u fd count cannot put\n", node->pid);
217 else
218 node->fd_count--;
219
220 ret = pthread_mutex_unlock(&node->fd_mtx);
221 if (ret != 0)
222 tloge("something wrong, get fd count unlock fd mtx fail\n");
223 }
224
225 /*
226 * return value means the fd number that be closed in exception_close_handle,
227 * the ref_cnt of drvcall node should be subtracted the same number
228 */
exception_close_handle(struct task_node * node)229 uint32_t exception_close_handle(struct task_node *node)
230 {
231 uint32_t close_fd_count = 0;
232 if (node == NULL) {
233 tloge("invalid node\n");
234 return close_fd_count;
235 }
236
237 int32_t ret = drv_mutex_lock(&node->fd_mtx);
238 if (ret != 0) {
239 tloge("get fd mtx lock fail\n");
240 return close_fd_count;
241 }
242
243 struct dlist_node *pos = NULL;
244 struct dlist_node *next = NULL;
245 struct fd_node *temp = NULL;
246 dlist_for_each_safe(pos, next, &node->fd_head) {
247 temp = dlist_entry(pos, struct fd_node, data_list);
248 if (temp->close_flag) {
249 tloge("fd:0x%llx has already call by close\n", temp->fd);
250 continue;
251 }
252
253 temp->close_flag = true;
254 close_fd_count++;
255 if (node->fd_count > 0)
256 node->fd_count--;
257 else
258 tloge("something wrong, fd count is zero\n");
259
260 dlist_delete(&temp->data_list);
261 tlogi("close fd:0x%llx in exception handle\n", temp->fd);
262
263 struct task_node *dnode = temp->drv;
264 if (dnode == NULL) {
265 tloge("something wrong, fd:0x%llx data has no drv\n", temp->fd);
266 } else {
267 ret = call_drv_close(node->pid, &node->tlv.uuid, temp->fd, dnode->drv_task.channel);
268 /* pair with dnode ref_cnt add one in open, called in drvcall fd_mtx lock */
269 put_node_with_lock(dnode, 1);
270 }
271
272 free(temp);
273 }
274
275 ret = pthread_mutex_unlock(&node->fd_mtx);
276 if (ret != 0)
277 tloge("something wrong, unlock mtx fd lock fail\n");
278
279 return close_fd_count;
280 }
281
282 #ifdef TEE_SUPPORT_DYN_CONF_DEBUG
dump_drvcall_fd(struct task_node * node)283 void dump_drvcall_fd(struct task_node *node)
284 {
285 if (node == NULL) {
286 tloge("dump invalid drvcall node\n");
287 return;
288 }
289
290 int32_t ret = drv_mutex_lock(&node->fd_mtx);
291 if (ret != 0) {
292 tloge("put fd count lock fd mtx fail\n");
293 return;
294 }
295
296 tlogi("\t[drvcall fd] fd_count:%u\n", node->fd_count);
297 dump_fd_node(node);
298
299 ret = pthread_mutex_unlock(&node->fd_mtx);
300 if (ret != 0)
301 tloge("something wrong, get fd count unlock fd mtx fail\n");
302 }
303 #endif
304