• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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