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 <string.h>
13 #include <sys/mman.h>
14 #include <mem_ops.h>
15 #include "ta_framework.h"
16 #include "tee_log.h"
17 #include "tee_init.h"
18 #include "tee_ext_api.h"
19 #include "tee_ss_agent_api.h"
20 #include "tee_mem_mgmt_api.h"
21 #include "sfs_internal.h"
22 #include "sfs.h"
23 #include "agent.h"
24 #include "securec.h"
25 #include "ipclib.h"
26 #include "ssa_enumerator.h"
27 #include "tee_internal_task_pub.h"
28 #include "ssa_fs.h"
29 #include <huk_service_msg.h>
30 #include <ipclib_hal.h>
31
32 bool g_is_ssa_reg = false;
33
34 /* structure for files of TAs */
35 static client_t g_clients[SRV_MAX_CLIENTS];
36
37 /* structure for files of TEE_OBJECT_STORAGE_PRIVATE */
38 static file_link_t g_private_storage[MAX_PRIVATE_OPEN_FILES];
39
40 struct ss_msg_queue_t g_ssa_msg_queue;
41
42 uint32_t g_global_handle;
43 uint32_t g_permsrv_handle;
44
45 static uint32_t g_arch_version = SFS_ARCH_VERSION_SSA;
46
47 TEE_UUID g_ssa_uuid = TEE_SERVICE_SSA;
48
get_sender_client_proc(uint32_t sender,char dead)49 static client_t *get_sender_client_proc(uint32_t sender, char dead)
50 {
51 uint32_t i;
52
53 for (i = 0; i < SRV_MAX_CLIENTS; i++) {
54 if (g_clients[i].task_id == sender && g_clients[i].dead == dead)
55 return &g_clients[i];
56 }
57 return NULL;
58 }
59
get_sender_client(uint32_t sender)60 client_t *get_sender_client(uint32_t sender)
61 {
62 return get_sender_client_proc(sender, 0);
63 }
64
is_client_register(uint32_t sender)65 bool is_client_register(uint32_t sender)
66 {
67 client_t *client = get_sender_client(sender);
68 if (client == NULL)
69 return false;
70
71 return true;
72 }
73
unreg_get_sender_client(uint32_t sender)74 static client_t *unreg_get_sender_client(uint32_t sender)
75 {
76 client_t *client = NULL;
77
78 client = get_sender_client_proc(sender, 1);
79 if (client == NULL)
80 client = get_sender_client_proc(sender, 0);
81
82 return client;
83 }
84
85 /* register TA. */
register_uuid(uint32_t sender,TEE_UUID uuid,uint32_t user_id,bool ssa_enum_enable)86 void register_uuid(uint32_t sender, TEE_UUID uuid, uint32_t user_id, bool ssa_enum_enable)
87 {
88 uint32_t i;
89 errno_t rc;
90
91 for (i = 0; i < SRV_MAX_CLIENTS; i++) {
92 if (g_clients[i].task_id == 0) {
93 rc = memset_s((void *)(&g_clients[i]), sizeof(g_clients[i]), 0, sizeof(client_t));
94 if (rc != EOK)
95 tloge("memset client %u failed, %x", i, rc);
96
97 g_clients[i].task_id = sender;
98 g_clients[i].user_id = user_id;
99 g_clients[i].ssa_enum_enable = ssa_enum_enable;
100 rc = memmove_s(&g_clients[i].uuid, sizeof(g_clients[i].uuid), &uuid, sizeof(TEE_UUID));
101 if (rc != EOK)
102 tloge("memmove failed %x\n", rc);
103
104 break;
105 }
106 }
107 if (i >= SRV_MAX_CLIENTS)
108 tloge("sfs register uuid session memory overflow, sender is 0x%x!\n", sender);
109 }
pre_unregister_remove_hmipccachech(const union ssa_agent_msg * msg,uint32_t sender)110 static void pre_unregister_remove_hmipccachech(const union ssa_agent_msg *msg, uint32_t sender)
111 {
112 uint32_t res_code;
113
114 if (msg == NULL) {
115 tloge(" invalid msg\n");
116 return;
117 }
118
119 if (sender == g_global_handle) {
120 tlogd("unregister task: %x\n", msg->reg.taskid);
121 (void)ipc_release_from_taskid(msg->reg.taskid, 0);
122 } else {
123 res_code = ipc_hunt_by_name(PERMSRV_SAVE_FILE, &g_permsrv_handle);
124 if (res_code != 0) {
125 g_permsrv_handle = 0;
126 tlogd("hunt by permsrv name error... %x\n", res_code);
127 return;
128 }
129 if (sender == g_permsrv_handle) {
130 tlogd("unregister task: %x\n", msg->reg.taskid);
131 (void)ipc_release_from_taskid(msg->reg.taskid, 0);
132 (void)ipc_release_by_name(PERMSRV_SAVE_FILE);
133 }
134 }
135
136 return;
137 }
138
pre_unregister_uuid(const union ssa_agent_msg * msg,uint32_t sender)139 char pre_unregister_uuid(const union ssa_agent_msg *msg, uint32_t sender)
140 {
141 client_t *tmp_client = NULL;
142 uint32_t i;
143 uint32_t files_count;
144 errno_t rc;
145
146 if (msg == NULL) {
147 tloge("pre UnRegisterUUID invalid msg\n");
148 return 0;
149 }
150
151 tlogd("preunregister 0x%x from %x\n", msg->reg.taskid, sender);
152
153 /* 1. search the client whitch is not dead */
154 tmp_client = get_sender_client_proc(msg->reg.taskid, 0);
155 if (tmp_client == NULL) {
156 tloge("Illegal client, not found any undead client sndr is 0x%x\n", sender);
157 return 0;
158 }
159
160 /* 2. check if this client havn't open file , then remove it at once. or mark is as dead */
161 files_count = 0;
162
163 for (i = 0; i < MAX_CLIENT_OPEN_FILES; i++) {
164 if (tmp_client->file_instance[i].file_link != NULL)
165 files_count++;
166 }
167
168 if (files_count == 0) {
169 pre_unregister_remove_hmipccachech(msg, sender);
170
171 rc = memset_s((void *)tmp_client, sizeof(client_t), 0, sizeof(client_t));
172 if (rc != EOK)
173 tloge("memset tmp client failed, %x\n", rc);
174 } else {
175 tmp_client->dead = 1;
176 tlogd("mark the client is dead.\n");
177 }
178
179 return tmp_client->dead;
180 }
181
182 /* unregister TA. */
unregister_uuid(uint32_t sender,const char * name)183 void unregister_uuid(uint32_t sender, const char *name)
184 {
185 uint32_t i;
186 errno_t rc;
187 meta_data_t *meta = NULL;
188 client_t *client = unreg_get_sender_client(sender);
189
190 tlogd("unregister start 0x%x\n", sender);
191
192 if (client == NULL) {
193 tloge("Illegal client, sender is 0x%x\n", sender);
194 return;
195 }
196
197 client->dead = 1;
198
199 (void)ipc_release_from_taskid(sender, 0);
200 (void)ipc_release_by_name(name);
201
202 for (i = 0; i < MAX_CLIENT_OPEN_FILES; i++) {
203 if ((client->file_instance[i].file_link) == NULL) {
204 continue;
205 }
206
207 if (client->file_instance[i].file_link->link_count == 0) {
208 client->file_instance[i].file_link = NULL;
209 continue;
210 }
211
212 tlogd("force clean %u\n", i + 1);
213
214 client->file_instance[i].file_link->link_count--;
215 if (client->file_instance[i].file_link->link_count == 0) {
216 meta = client->file_instance[i].file_link->sfd->meta_data;
217 (void)ssa_close(client->file_instance[i].file_link->sfd);
218 client->file_instance[i].file_link->sfd = 0;
219 free_meta_data(&meta);
220 }
221
222 client->file_instance[i].file_link = NULL;
223 }
224
225 rc = memset_s((void *)&(client->uuid), sizeof(client->uuid), 0, sizeof(TEE_UUID));
226 if (rc != EOK)
227 tlogw("memset failed, %x\n", rc);
228
229 client->task_id = 0;
230 client->dead = 0;
231 client->ssa_enum_enable = false;
232 tlogd("Done\n");
233 }
234
is_enum_enable(const TEE_UUID * uuid)235 bool is_enum_enable(const TEE_UUID *uuid)
236 {
237 uint32_t i;
238 bool find = true;
239
240 if (uuid == NULL)
241 return false;
242
243 for (i = 0; i < SRV_MAX_CLIENTS; i++) {
244 find = (TEE_MemCompare(uuid, &(g_clients[i].uuid), sizeof(TEE_UUID)) == 0) && g_clients[i].ssa_enum_enable;
245 if (find)
246 return true;
247 }
248
249 return false;
250 }
get_sender_userid(uint32_t sender)251 static uint32_t get_sender_userid(uint32_t sender)
252 {
253 client_t *client = get_sender_client(sender);
254
255 if (client == NULL) {
256 uint32_t i_count;
257 uint32_t count = 0;
258 tloge("dump userid the client array!\n");
259 for (i_count = 0; i_count < SRV_MAX_CLIENTS; i_count++)
260 if (g_clients[i_count].task_id != 0) {
261 tloge("%uth taskid %x uuid %x dead is %x!\n", i_count, g_clients[i_count].task_id,
262 g_clients[i_count].uuid.timeLow, g_clients[i_count].dead);
263 count++;
264 }
265 tloge("Illegal client, sndr is 0x%x, count is 0x%x!\n", sender, count);
266 return 0;
267 }
268
269 return (client->user_id);
270 }
271
get_sender_uuid(uint32_t sender)272 TEE_UUID *get_sender_uuid(uint32_t sender)
273 {
274 client_t *client = get_sender_client(sender);
275
276 if (client == NULL) {
277 uint32_t i_count;
278 uint32_t count = 0;
279 tloge("dump uuid the client array!\n");
280 for (i_count = 0; i_count < SRV_MAX_CLIENTS; i_count++)
281 if (g_clients[i_count].task_id != 0) {
282 tloge("%uth taskid %x uuid %x dead is %x!\n", i_count, g_clients[i_count].task_id,
283 g_clients[i_count].uuid.timeLow, g_clients[i_count].dead);
284 count++;
285 }
286 tloge("Illegal client, sndr is 0x%x, count is 0x%x!\n", sender, count);
287 return 0;
288 }
289
290 return (&client->uuid);
291 }
292
get_current_uuid(void)293 TEE_UUID *get_current_uuid(void)
294 {
295 return (&g_ssa_uuid);
296 }
297
298 /* check shared accesses.
299 * see: TEE Internal Core API Specification - Public Review v1.2.0.1
300 * Paragraph: 5.8.3 Persistent Object Sharing Rules
301 * Multiple handles may be opened on the same object simultaneously using the functions
302 * TEE_OpenPersistentObject or TEE_CreatePersistentObject, but sharing MUST be explicitly allowed.
303 * More precisely, at any one time the following constraints apply: If more than one handle is opened
304 * on the same object, and if any of these object handles was opened with the
305 * flag TEE_DATA_FLAG_ACCESS_READ, then all the object handles MUST have been opened with the
306 * flag TEE_DATA_FLAG_SHARE_READ. There is a corresponding constraint with the
307 * flags TEE_DATA_FLAG_ACCESS_WRITE and TEE_DATA_FLAG_SHARE_WRITE.
308 * Accessing an object with write-meta rights is exclusive and can never be shared.
309 */
check_shared_access(const struct sfd_t * sfd,uint32_t flags)310 bool check_shared_access(const struct sfd_t *sfd, uint32_t flags)
311 {
312 bool status = true;
313
314 if (sfd == NULL)
315 return false;
316 tlogd("start prev:%x - this: %x \n", sfd->flags, flags);
317 /*
318 * shared read access is allowed only if both (the first an this one)
319 * has TEE_DATA_FLAG_SHARE_READ set
320 */
321 if ((flags & TEE_DATA_FLAG_ACCESS_READ) && !(sfd->flags & flags & TEE_DATA_FLAG_SHARE_READ)) {
322 tlogd("shared read - no access\n");
323 status = false;
324 }
325 /*
326 * shared write access is allowed only if both (the first an this one)
327 * has TEE_DATA_FLAG_SHARE_WRITE set
328 */
329 if ((flags & TEE_DATA_FLAG_ACCESS_WRITE) && !(sfd->flags & flags & TEE_DATA_FLAG_SHARE_WRITE)) {
330 tlogd("shared write - no access\n");
331 status = false;
332 }
333 /* shared access is not allowed with TEE_DATA_FLAG_ACCESS_WRITE_META */
334 if ((flags & TEE_DATA_FLAG_ACCESS_WRITE_META) || (sfd->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) {
335 tlogd("write meta - no access\n");
336 status = false;
337 }
338
339 if (flags == 0) {
340 tlogd("flags - no access\n");
341 status = false;
342 }
343
344 return status;
345 }
346 /*
347 * check if there is already opened file descriptor for this file.
348 * if there is, return pointer to it. Otherwise return null.
349 */
find_already_open(const meta_data_t * meta)350 static file_link_t *find_already_open(const meta_data_t *meta)
351 {
352 uint32_t i;
353
354 if (meta == NULL || (meta->file_id) == NULL)
355 return NULL;
356
357 for (i = 0; i < MAX_PRIVATE_OPEN_FILES; i++) {
358 if (g_private_storage[i].link_count) {
359 if ((TEE_MemCompare(&g_private_storage[i].sfd->meta_data->uuid, &meta->uuid, sizeof(TEE_UUID)) == 0) &&
360 (g_private_storage[i].first_opened) &&
361 (g_private_storage[i].sfd->meta_data->file_id_len == meta->file_id_len) &&
362 (TEE_MemCompare(g_private_storage[i].sfd->meta_data->file_id, meta->file_id, meta->file_id_len) == 0)) {
363 tlogd("file has been opened in %u\n", i);
364 return &g_private_storage[i];
365 }
366 }
367 }
368
369 return NULL;
370 }
371
372 /*
373 * There is no open file file descriptor for this file.
374 * We create a new one and also create a new file instance of client
375 */
create_file_instance_to_client(uint32_t sender,struct sfd_t * sfd)376 uint32_t create_file_instance_to_client(uint32_t sender, struct sfd_t *sfd)
377 {
378 uint32_t k;
379 file_link_t *flink = NULL;
380 client_t *client = get_sender_client(sender);
381 bool temp = false;
382
383 if (client == NULL || sfd == NULL) {
384 tloge("Illegal client or sfd\n");
385 return 0;
386 }
387
388 for (k = 0; k < MAX_PRIVATE_OPEN_FILES; k++) {
389 if (g_private_storage[k].link_count == 0) {
390 flink = &g_private_storage[k];
391 break;
392 }
393 }
394
395 if (flink == NULL) {
396 tloge("Too many open files\n");
397 return 0;
398 }
399
400 for (uint32_t i = 0; i < MAX_CLIENT_OPEN_FILES; i++) {
401 if (client->file_instance[i].file_link != NULL)
402 continue;
403
404 client->file_instance[i].file_link = flink;
405 client->file_instance[i].seek_position = 0;
406 client->file_instance[i].file_link->sfd = sfd;
407 client->file_instance[i].file_link->link_count = 1;
408 client->file_instance[i].file_link->first_opened = true;
409 /* check the first opened obj */
410 for (uint32_t j = 0; j < MAX_PRIVATE_OPEN_FILES; j++) {
411 if (k == j)
412 continue;
413 if (g_private_storage[j].link_count == 0)
414 continue;
415
416 temp = (sfd->meta_data->file_id_len == g_private_storage[j].sfd->meta_data->file_id_len) &&
417 (TEE_MemCompare(sfd->meta_data->file_id, g_private_storage[j].sfd->meta_data->file_id,
418 sfd->meta_data->file_id_len) == 0) &&
419 (TEE_MemCompare(&g_private_storage[j].sfd->meta_data->uuid, &sfd->meta_data->uuid,
420 sizeof(TEE_UUID)) == 0);
421 if (temp) {
422 client->file_instance[i].file_link->first_opened = false;
423 break;
424 }
425 }
426 return i + 1;
427 }
428
429 tloge("Too many open files\n");
430 return 0;
431 }
432
433 /*
434 * Close the file. If there are no more instances of this file
435 * then internal file handle of file is closed.
436 */
close_file_from_client(uint32_t sender,uint32_t obj)437 void close_file_from_client(uint32_t sender, uint32_t obj)
438 {
439 tlogd("start\n");
440 client_t *client = get_sender_client(sender);
441 meta_data_t *meta = NULL;
442
443 if (client == NULL) {
444 tloge("Illegal client\n");
445 return;
446 }
447
448 if ((obj == 0) || (obj > MAX_CLIENT_OPEN_FILES)) {
449 tloge("illegal objID 0x%x\n", obj);
450 return;
451 }
452 if (client->file_instance[obj - 1].file_link == NULL) {
453 tloge("non-existing instance for object %u\n", obj);
454 return;
455 }
456
457 tlogd("file %s\n", client->file_instance[obj - 1].file_link->sfd->meta_data->file_id);
458 tlogd("link_count %d\n", client->file_instance[obj - 1].file_link->link_count);
459
460 if (client->file_instance[obj - 1].file_link->link_count == 0)
461 return;
462
463 client->file_instance[obj - 1].file_link->link_count--;
464
465 if (client->file_instance[obj - 1].file_link->link_count == 0) {
466 tlogd("No more links to file, close it\n");
467
468 meta = client->file_instance[obj - 1].file_link->sfd->meta_data;
469 (void)ssa_close(client->file_instance[obj - 1].file_link->sfd);
470 client->file_instance[obj - 1].file_link->sfd = 0;
471
472 free_meta_data(&meta);
473 /* filelink is not in use anymore, it can be free */
474 client->file_instance[obj - 1].file_link->first_opened = false;
475 } else {
476 /* there is other instance(s) for this file, handler must not be closed. */
477 tlogd("More links to file, Sync only\n");
478 /* do sync() if obj has write access */
479 if (client->file_instance[obj - 1].file_link->sfd->flags & TEE_DATA_FLAG_ACCESS_WRITE) {
480 if (ssa_sync(client->file_instance[obj - 1].file_link->sfd) != TEE_SUCCESS)
481 tlogd("ssa sync return error\n");
482 }
483 }
484
485 tlogd("remove obj from 0x%x/%u\n", sender, obj);
486 client->file_instance[obj - 1].file_link = 0;
487
488 return;
489 }
490
get_file_handle(meta_data_t * meta,uint32_t sndr,uint32_t flags,struct sfd_t ** sfd,TEE_Result * error)491 static uint32_t get_file_handle(meta_data_t *meta, uint32_t sndr,
492 uint32_t flags, struct sfd_t **sfd, TEE_Result *error)
493 {
494 uint32_t handle;
495
496 if (error == NULL)
497 return 0;
498
499 if (sfd == NULL || meta == NULL) {
500 *error = TEE_ERROR_BAD_PARAMETERS;
501 return 0;
502 }
503
504 set_meta_data_verion(meta, SFS_ARCH_VERSION_SSA);
505 *sfd = ssa_open(meta, flags, error);
506 if (*error == TEE_SUCCESS) {
507 tlogd("open success version C\n");
508 handle = create_file_instance_to_client(sndr, *sfd);
509 if (handle == 0) {
510 (void)ssa_close(*sfd);
511 *sfd = NULL;
512 *error = TEE_ERROR_STORAGE_EMFILE;
513 }
514 return handle;
515 }
516
517 return 0;
518 }
519
520 /*
521 * try to open file.
522 * First checks if file is already opened, if it is, use
523 * existing secure file descriptor (SFD) and create new file instance that contains
524 * existing SFD.
525 * If file is not open, create a new SFD and file instance for it.
526 *
527 * This will allow that TA can open same object several times and all the opens
528 * are always in sync.
529 *
530 * see TEE Internal Core API Specification - Public Review v1.2.0.1
531 * Paragraph 5.8.1 TEE_OpenPersistentObject
532 * ...
533 * Multiple handles may be opened on the same object simultaneously, but sharing MUST
534 * be explicitly allowed as described in section 5.8.3.
535 */
open_file(meta_data_t * meta,uint32_t sndr,uint32_t flags,struct sfd_t ** sfd,TEE_Result * error)536 uint32_t open_file(meta_data_t *meta, uint32_t sndr, uint32_t flags, struct sfd_t **sfd, TEE_Result *error)
537 {
538 uint32_t handle;
539
540 if (error == NULL)
541 return 0;
542
543 if (sfd == NULL || meta == NULL) {
544 *error = TEE_ERROR_BAD_PARAMETERS;
545 return 0;
546 }
547
548 file_link_t *flink = find_already_open(meta);
549 if (flink != NULL && flink->sfd != NULL) {
550 if (!check_shared_access(flink->sfd, flags)) {
551 *error = TEE_ERROR_ACCESS_CONFLICT;
552 return 0;
553 }
554 }
555
556 handle = get_file_handle(meta, sndr, flags, sfd, error);
557 return handle;
558 }
559
560 /*
561 * Delete file from storage.
562 * obj is an index of open files of TA.
563 * TEE Internal Core API Specification - Public Review v1.2.0.1
564 * 5.8.5 TEE_CloseAndDeletePersistentObject1
565 * Deleting an object is atomic; once this function returns, the object is definitely deleted
566 * and no more open handles for the object exist. This SHALL be the case even if the object or
567 * the storage containing it have become corrupted
568 */
delete_file(uint32_t sender,uint32_t obj)569 TEE_Result delete_file(uint32_t sender, uint32_t obj)
570 {
571 tlogd("start %u\n", obj);
572 client_t *client = get_sender_client(sender);
573 meta_data_t *meta = NULL;
574 TEE_Result ret;
575
576 if (client == NULL) {
577 tloge("Illegal client for sender 0x%x\n", sender);
578 return TEE_ERROR_BAD_PARAMETERS;
579 }
580
581 if ((obj == 0) || (obj > MAX_CLIENT_OPEN_FILES)) {
582 tloge("illegal obj 0x%x\n", obj);
583 return TEE_SUCCESS;
584 }
585
586 /* check that file link exist. */
587 if ((client->file_instance[obj - 1].file_link) == NULL)
588 return TEE_SUCCESS;
589
590 tlogd("link count 0x%x/%u %d\n", sender, obj, client->file_instance[obj - 1].file_link->link_count);
591
592 if ((client->file_instance[obj - 1].file_link->sfd) == NULL)
593 return TEE_SUCCESS;
594
595 meta = client->file_instance[obj - 1].file_link->sfd->meta_data;
596 ret = ssa_close_and_delete(client->file_instance[obj - 1].file_link->sfd, true);
597 if (ret != TEE_SUCCESS)
598 tloge("ssa_close_and_delete fail, ret %x\n", ret);
599
600 client->file_instance[obj - 1].file_link->sfd = NULL;
601
602 free_meta_data(&meta);
603
604 if (client->file_instance[obj - 1].file_link->link_count) {
605 client->file_instance[obj - 1].file_link->link_count--;
606 /* file descriptor have to be released by each instances until it can be reused */
607 tlogd("there are still %d users of deleted file\n", client->file_instance[obj - 1].file_link->link_count);
608 }
609 client->file_instance[obj - 1].file_link = NULL;
610
611 return ret;
612 }
613
614 struct ssa_caller_info_t {
615 uint32_t sndr;
616 uint32_t user_id;
617 };
618 struct ssa_caller_info_t g_caller_info = { 0 };
set_ssa_caller_info(uint32_t sndr,uint32_t cmd)619 static TEE_Result set_ssa_caller_info(uint32_t sndr, uint32_t cmd)
620 {
621 TEE_Result ret;
622
623 if (g_permsrv_handle == 0) {
624 if (ipc_hunt_by_name(PERMSRV_SAVE_FILE, &g_permsrv_handle) != 0)
625 g_permsrv_handle = 0;
626 }
627
628 /* only unreg msg from globaltask need process. */
629 if (sndr == g_global_handle && cmd != TEE_TASK_CLOSE_TA_SESSION && cmd != SS_AGENT_LOAD_MANAGE_INFO)
630 return TEE_SUCCESS;
631
632 ret = set_caller_info_proc(sndr, cmd);
633 if (ret != TEE_SUCCESS)
634 return ret;
635
636 g_caller_info.sndr = sndr;
637
638 if (g_permsrv_handle != 0 && sndr == g_permsrv_handle)
639 g_caller_info.user_id = 0;
640 else
641 g_caller_info.user_id = get_sender_userid(sndr);
642
643 return TEE_SUCCESS;
644 }
645
get_ree_user_id(void)646 uint32_t get_ree_user_id(void)
647 {
648 return g_caller_info.user_id;
649 }
650
ssa_map_from_task(uint32_t in_task_id,uint64_t va_addr,uint32_t size,uint32_t out_task_id,uintptr_t * vm_addr)651 int ssa_map_from_task(uint32_t in_task_id, uint64_t va_addr, uint32_t size, uint32_t out_task_id, uintptr_t *vm_addr)
652 {
653 (void)out_task_id;
654 uint64_t out_addr;
655 int ret;
656
657 /* It will definitely not be NULL, do we really need to check every param ? */
658 if (vm_addr == NULL)
659 return -1;
660
661 ret = map_sharemem(in_task_id, va_addr, size, &out_addr);
662 if (ret == 0) {
663 *vm_addr = (uintptr_t)out_addr;
664 if (*vm_addr == 0)
665 return -1;
666 } else {
667 tloge("map initialData from %u fail\n", in_task_id);
668 return ret;
669 }
670
671 return 0;
672 }
ssa_unmap_from_task(uint32_t task_id,uintptr_t va_addr,uint32_t size,bool mapped)673 void ssa_unmap_from_task(uint32_t task_id, uintptr_t va_addr, uint32_t size, bool mapped)
674 {
675 (void)task_id;
676 if (mapped == false) {
677 tlogd("ssa_unmap_from_task map is false");
678 return;
679 }
680
681 (void)unmap_sharemem((void *)va_addr, size);
682 }
683
ssa_write_attributes(const uint8_t * attributes,uint32_t attributes_len,struct sfd_t * sfd,uint32_t arch_version,TEE_Result * error)684 static void ssa_write_attributes(const uint8_t *attributes, uint32_t attributes_len, struct sfd_t *sfd,
685 uint32_t arch_version, TEE_Result *error)
686 {
687 uint32_t ret;
688
689 (void)arch_version;
690 if (attributes == 0 || attributes_len == 0) {
691 /* no need to write attributes, not error */
692 *error = TEE_SUCCESS;
693 return;
694 }
695
696 /* write attribute */
697 ret = ssa_write(attributes, attributes_len, sfd, error);
698 if ((ret != attributes_len) || (*error != TEE_SUCCESS)) {
699 tloge("write attributes fail, error:0x%x", *error);
700 *error = TEE_ERROR_GENERIC;
701 return;
702 }
703 sfd->attr_size = attributes_len;
704
705 *error = TEE_SUCCESS;
706 }
707
ssa_write_initial_data(const uint8_t * initial_data,uint32_t data_len,struct sfd_t * sfd,TEE_Result * error)708 static void ssa_write_initial_data(const uint8_t *initial_data, uint32_t data_len, struct sfd_t *sfd,
709 TEE_Result *error)
710 {
711 uint32_t ret;
712
713 if (initial_data == 0 || data_len == 0) {
714 /* no need to write initial data, not error */
715 *error = TEE_SUCCESS;
716 return;
717 }
718
719 /* write initial data */
720 ret = ssa_write(initial_data, data_len, sfd, error);
721 if ((ret != data_len) || (*error != TEE_SUCCESS)) {
722 tloge("write initialData fail, error:0x%x", *error);
723 *error = TEE_ERROR_GENERIC;
724 return;
725 }
726
727 *error = TEE_SUCCESS;
728 }
729
create_permission_check(const meta_data_t * meta,uint32_t flags)730 static TEE_Result create_permission_check(const meta_data_t *meta, uint32_t flags)
731 {
732 /* check if file with same name already exist. Bad news, we can't use TEE_DATA_FLAG_OVERWRITE in GP v1.1 */
733 bool check_obj_fail = (meta->cur_encrypted_file_id == NULL) || (((TEE_DATA_FLAG_EXCLUSIVE & flags) != 0) &&
734 (ssa_fs_faccess((char *)meta->cur_encrypted_file_id, F_OK, meta->storage_id) == 0));
735 if (check_obj_fail) {
736 tloge("file exists: conflict to recreate\n");
737 return TEE_ERROR_ACCESS_CONFLICT;
738 }
739
740 /* check file with same name is already open. it is have to be opened by same TA */
741 file_link_t *flink = find_already_open(meta);
742 if (flink != NULL) {
743 bool check_fail = (flink->sfd == NULL) || (!check_shared_access(flink->sfd, flags));
744 if (check_fail) {
745 tloge("no access to recreate!\n");
746 return TEE_ERROR_ACCESS_CONFLICT;
747 }
748 }
749
750 return TEE_SUCCESS;
751 }
752
create_object(const struct create_obj_msg_t * create_obj,uint32_t sndr,const TEE_UUID * uuid,struct sfd_t ** sfd,uint32_t * obj,TEE_Result * error)753 void create_object(const struct create_obj_msg_t *create_obj, uint32_t sndr, const TEE_UUID *uuid,
754 struct sfd_t **sfd, uint32_t *obj, TEE_Result *error)
755 {
756 bool check_param_invalid = (create_obj == NULL) || (uuid == NULL) || (sfd == NULL) ||
757 (error == NULL) || (create_obj->object_id == 0) || (obj == NULL);
758 if (check_param_invalid)
759 return;
760
761 meta_data_t *meta = create_meta_data((uint8_t *)(uintptr_t)create_obj->object_id, create_obj->obj_id_len,
762 create_obj->storage_id, create_obj->flags, uuid, error, g_arch_version);
763 if (meta == NULL) {
764 tloge("meta create fail\n");
765 return;
766 }
767
768 TEE_Result ret = create_permission_check(meta, create_obj->flags);
769 if (ret != TEE_SUCCESS) {
770 *error = ret;
771 goto clean1;
772 }
773
774 *sfd = ssa_create(meta, create_obj->flags, error);
775 if ((*sfd == NULL) || (*error != TEE_SUCCESS)) {
776 tloge("create fail\n");
777 goto clean1;
778 }
779
780 ssa_write_attributes((uint8_t *)(uintptr_t)create_obj->attributes, create_obj->attributes_len, *sfd,
781 meta->arch_version, error);
782 if (*error != TEE_SUCCESS) {
783 goto clean2;
784 }
785
786 ssa_write_initial_data((uint8_t *)(uintptr_t)create_obj->initial_data, create_obj->data_len, *sfd, error);
787 if (*error != TEE_SUCCESS) {
788 goto clean2;
789 }
790
791 (*sfd)->need_update_hmac = false;
792
793 *error = ssa_write_mac(*sfd);
794 if (*error != TEE_SUCCESS) {
795 tloge("write mac fail %x", *error);
796 goto clean2;
797 }
798
799 *obj = create_file_instance_to_client(sndr, *sfd);
800 if (*obj == 0) {
801 *error = TEE_ERROR_GENERIC;
802 goto clean2;
803 }
804
805 return;
806 clean2:
807 (void)ssa_close_and_delete(*sfd, false);
808 clean1:
809 free_meta_data(&meta);
810 }
811
copy_and_check_file_name(const char * obj_id_in,uint32_t in_len,char * obj_id,uint32_t obj_len)812 TEE_Result copy_and_check_file_name(const char *obj_id_in, uint32_t in_len, char *obj_id, uint32_t obj_len)
813 {
814 int32_t rc;
815 TEE_Result ret;
816
817 if (obj_id_in == NULL || obj_id == NULL)
818 return TEE_ERROR_BAD_PARAMETERS;
819
820 if (obj_len == 0 || obj_len - 1 < in_len)
821 return TEE_ERROR_BAD_PARAMETERS;
822
823 rc = memcpy_s(obj_id, obj_len - 1, obj_id_in, in_len);
824 if (rc != EOK) {
825 tloge("file name copy failed!");
826 return TEE_ERROR_SECURITY;
827 }
828 obj_id[obj_len - 1] = '\0';
829
830 ret = check_file_name(obj_id);
831 if (ret != TEE_SUCCESS)
832 tloge("file name is invalid!");
833
834 return ret;
835 }
836
837 #define WEAK __attribute__((weak))
838
839 #define BSS_START_MAGIC 0x12345678
840 #define BSS_END_MAGIC 0x87654321
841 WEAK UINT32 TA_BSS_START = BSS_START_MAGIC;
842 WEAK UINT32 TA_BSS_END = BSS_END_MAGIC;
843
844 typedef void (*func_ptr)(void);
845 extern func_ptr WEAK __init_array_start[];
846 extern func_ptr WEAK __init_array_end[];
847
ssa_file_process_abort(union ssa_agent_msg * msg,uint32_t sndr,struct ssa_agent_rsp * rsp)848 void ssa_file_process_abort(union ssa_agent_msg *msg, uint32_t sndr, struct ssa_agent_rsp *rsp)
849 {
850 uint32_t obj;
851
852 if (rsp == NULL)
853 return;
854
855 if (msg == NULL) {
856 tloge("invalid msg!\n");
857 rsp->ret = TEE_ERROR_BAD_PARAMETERS;
858 return;
859 }
860
861 obj = msg->write_obj.obj_index;
862
863 file_instance_t *fpointer = get_file_pointer(sndr, obj);
864 bool check_ptr_null = (fpointer == NULL) || (fpointer->file_link == NULL) || (fpointer->file_link->sfd == NULL);
865 if (check_ptr_null) {
866 tloge("get session Fail\n");
867 return;
868 }
869
870 fpointer->file_link->sfd->need_update_hmac = false;
871 fpointer->file_link->sfd->update_backup = false;
872 return;
873 }
874
ssa_register_agent(union ssa_agent_msg * msg,uint32_t sndr,struct ssa_agent_rsp * rsp)875 void ssa_register_agent(union ssa_agent_msg *msg, uint32_t sndr, struct ssa_agent_rsp *rsp)
876 {
877 uint64_t fs_agent_buffer = 0;
878
879 if (rsp == NULL)
880 return;
881
882 if (msg == NULL) {
883 tloge("invalid msg!\n");
884 rsp->ret = TEE_ERROR_BAD_PARAMETERS;
885 return;
886 }
887
888 if (g_is_ssa_reg == true) {
889 tloge("only allow registration once!\n");
890 return;
891 }
892
893 if (sndr != g_global_handle) {
894 tloge("not send fromb global %x\n", sndr);
895 return;
896 }
897 if (msg->reg_agent.agentid == TEE_FS_AGENT_ID) {
898 if (task_map_ns_phy_mem(g_ssagent_handle, (uint64_t)msg->reg_agent.phys_addr,
899 msg->reg_agent.size, &fs_agent_buffer)) {
900 tloge("map fs agent buffer fail\n");
901 } else {
902 tlogd("map fs agent buffer from %x to %lx, size=%u\n", msg->reg_agent.phys_addr, fs_agent_buffer,
903 msg->reg_agent.size);
904 (void)tee_fs_init((void *)(uintptr_t)fs_agent_buffer);
905 g_is_ssa_reg = true;
906 }
907 } else {
908 tloge("no need to config agentid: 0x%x\n", msg->reg_agent.agentid);
909 }
910 return;
911 }
912
ssa_register_uuid(union ssa_agent_msg * msg,uint32_t sndr,struct ssa_agent_rsp * rsp)913 void ssa_register_uuid(union ssa_agent_msg *msg, uint32_t sndr, struct ssa_agent_rsp *rsp)
914 {
915 (void)rsp;
916
917 if (msg == NULL) {
918 tloge("ssa_register_uuid invalid msg\n");
919 return;
920 }
921
922 /* must get the permsrv handle, because the permsrv may restart. other place don't need. */
923 if (ipc_hunt_by_name(PERMSRV_SAVE_FILE, &g_permsrv_handle) != 0)
924 g_permsrv_handle = 0;
925
926 if (sndr == g_global_handle || sndr == g_permsrv_handle) {
927 tlogd("register task: %x-%x\n", msg->reg.taskid, msg->reg.uuid.timeLow);
928 register_uuid(msg->reg.taskid, msg->reg.uuid, msg->reg.userid, msg->reg.ssa_enum_enable);
929 }
930 }
931
ssa_unregister_uuid(union ssa_agent_msg * msg,uint32_t sndr,struct ssa_agent_rsp * rsp)932 static void ssa_unregister_uuid(union ssa_agent_msg *msg, uint32_t sndr, struct ssa_agent_rsp *rsp)
933 {
934 (void)rsp;
935
936 if (msg == NULL) {
937 tloge("ssa_unregister_uuid invalid msg\n");
938 return;
939 }
940
941 if (ipc_hunt_by_name(PERMSRV_SAVE_FILE, &g_permsrv_handle) != 0)
942 g_permsrv_handle = 0;
943
944 if (sndr == g_global_handle) {
945 tlogd("unregister task: %x\n", msg->reg.taskid);
946
947 unregister_uuid(msg->reg.taskid, NULL);
948 } else if (sndr == g_permsrv_handle) {
949 tlogd("unregister task: %x\n", msg->reg.taskid);
950 unregister_uuid(msg->reg.taskid, PERMSRV_SAVE_FILE);
951 }
952 }
953
954 /*
955 * TA's main entry
956 */
957 ssa_cmd_t g_ssa_cmd_tbl[] = {
958 /* ssa register msg */
959 {TEE_TASK_REGISTER_AGENT, 0, NOT_FILE_OPERATION, NOT_FILE_MODIFY, ssa_register_agent},
960 {TEE_TASK_OPEN_TA_SESSION, 0, NOT_FILE_OPERATION, NOT_FILE_MODIFY, ssa_register_uuid},
961 {TEE_TASK_CLOSE_TA_SESSION, 0, NOT_FILE_OPERATION, NOT_FILE_MODIFY, ssa_unregister_uuid},
962
963 /* file opertion , need ssa register done. */
964 {SS_AGENT_CREATE_OBJECT, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_create_object},
965 {SS_AGENT_OPEN_OBJECT, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_open_object},
966 {SS_AGENT_READ_OBJECT, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_read_object},
967 {SS_AGENT_WRITE_OBJECT, 1, FILE_OPERATION, FILE_MODIFY, ssa_write_object},
968 {SS_AGENT_SEEK_OBJECT, 1, FILE_OPERATION, FILE_MODIFY, ssa_seek_object},
969 {SS_AGENT_TRUNCATE_OBJECT, 1, FILE_OPERATION, FILE_MODIFY, ssa_truncate_object},
970 {SS_AGENT_RENAME_OBJECT, 1, FILE_OPERATION, FILE_MODIFY, ssa_rename_object},
971 {SS_AGENT_GET_OBJECT_INFO, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_info_object},
972 {SS_AGENT_GET_OBJECT_ATTRIBUTES, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_get_object_attr},
973 {SS_AGENT_CLOSE_OBJECT, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_close_object},
974 {SS_AGENT_SYNC_OBJECT, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_sync_object},
975 {SS_AGENT_CLOSE_AND_DELETE_OBJECT, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_close_and_delete_object},
976 {SS_AGENT_FILE_ABORT, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_file_process_abort},
977 {SS_AGENT_GET_ENUM_FILE_SIZE, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_get_enum_file_size},
978 {SS_AGENT_START_ENUMERATOR, 1, FILE_OPERATION, NOT_FILE_MODIFY, ssa_start_enumerator},
979 };
980
981 uint32_t g_ssa_cmd_num = sizeof(g_ssa_cmd_tbl) / sizeof(g_ssa_cmd_tbl[0]);
982
ssa_find_cmd(uint32_t cmd)983 ssa_cmd_t *ssa_find_cmd(uint32_t cmd)
984 {
985 uint32_t i;
986
987 for (i = 0; i < g_ssa_cmd_num; i++) {
988 if (cmd != g_ssa_cmd_tbl[i].cmd) {
989 continue;
990 }
991
992 break;
993 }
994
995 if (i >= g_ssa_cmd_num) {
996 tloge("ssa cmd not in tbl or cmd is file operation : %x\n", cmd);
997 return NULL;
998 }
999
1000 return &g_ssa_cmd_tbl[i];
1001 }
1002
init_global_param(void)1003 void init_global_param(void)
1004 {
1005 (void)memset_s(g_clients, sizeof(g_clients), 0, sizeof(g_clients));
1006 (void)memset_s((void *)g_private_storage, sizeof(g_private_storage), 0, sizeof(g_private_storage));
1007 (void)memset_s((void *)(&g_ssa_msg_queue), sizeof(g_ssa_msg_queue), 0xFF, sizeof(g_ssa_msg_queue));
1008 g_ssa_msg_queue.in = 0;
1009 g_ssa_msg_queue.out = 0;
1010 }
1011
task_entry_init(int32_t init_build)1012 static void task_entry_init(int32_t init_build)
1013 {
1014 (void)init_build;
1015 g_is_ssa_reg = false;
1016
1017 init_global_param();
1018 }
1019
ssa_cmd_proc(uint32_t cmd,uint32_t sndr,union ssa_agent_msg * msg)1020 static void ssa_cmd_proc(uint32_t cmd, uint32_t sndr, union ssa_agent_msg *msg)
1021 {
1022 bool need_ack = false;
1023 uint32_t i;
1024 struct ssa_agent_rsp rsp;
1025 uint32_t res_code;
1026
1027 (void)memset_s((void *)(&rsp), sizeof(rsp), 0, sizeof(rsp));
1028
1029 for (i = 0; i < g_ssa_cmd_num; i++) {
1030 if (cmd != g_ssa_cmd_tbl[i].cmd)
1031 continue;
1032
1033 need_ack = g_ssa_cmd_tbl[i].need_ack;
1034
1035 if (g_ssa_cmd_tbl[i].is_file_oper == FILE_OPERATION && !g_is_ssa_reg) {
1036 tloge("ssa object cmd 0x%x: ssa is not register\n", cmd);
1037 rsp.ret = TEE_ERROR_STORAGE_NOT_AVAILABLE;
1038 } else if (g_ssa_cmd_tbl[i].fn != NULL) {
1039 g_ssa_cmd_tbl[i].fn(msg, sndr, &rsp);
1040 if (g_ssa_cmd_tbl[i].is_file_modify == FILE_MODIFY && rsp.ret != TEE_SUCCESS) {
1041 tloge("ssa object cmd 0x%x: file is dirty, process abort\n", cmd);
1042 ssa_file_process_abort(msg, sndr, &rsp);
1043 }
1044 } else {
1045 tloge("no process func for cmd 0x%x, from 0x%x", cmd, sndr);
1046 }
1047 break;
1048 }
1049
1050 if (i >= g_ssa_cmd_num) {
1051 tloge("ssa cmd not in tbl: 0x%x, from 0x%x\n", cmd, sndr);
1052 return;
1053 }
1054
1055 if (!need_ack)
1056 return;
1057
1058 res_code = (uint32_t)ipc_msg_snd(cmd, sndr, (void *)&rsp, sizeof(struct ssa_agent_rsp));
1059 if (res_code != 0)
1060 tloge("msg snd error 0x%x\n", res_code);
1061 }
1062
ssa_receive_msg(uint32_t uw_timeout,uint32_t * puw_msg_id,void * msgp,uint16_t size,uint32_t * puw_sender_pid)1063 static uint32_t ssa_receive_msg(uint32_t uw_timeout, uint32_t *puw_msg_id, void *msgp,
1064 uint16_t size, uint32_t *puw_sender_pid)
1065 {
1066 (void)uw_timeout;
1067 return ssa_get_msg(puw_msg_id, msgp, size, puw_sender_pid);
1068 }
1069
ssa_handle_msg(void * arg)1070 void *ssa_handle_msg(void *arg)
1071 {
1072 TEE_Result ret;
1073 uint32_t cmd = 0;
1074 uint32_t sndr = 0;
1075 union ssa_agent_msg msg;
1076 struct ssa_agent_rsp rsp;
1077 (void)arg;
1078 uint32_t global_taskid;
1079
1080 ret = ipc_hunt_by_name(GLOBAL_SERVICE_NAME, &global_taskid);
1081 if (ret != TEE_SUCCESS) {
1082 tloge("hunt by gb name error 0x%x\n", ret);
1083 return NULL;
1084 }
1085 g_global_handle = taskid_to_pid(global_taskid);
1086 set_global_handle(g_global_handle);
1087
1088 while (1) {
1089 ret = memset_s(&msg, sizeof(msg), 0, sizeof(msg));
1090 if (ret != TEE_SUCCESS)
1091 tlogw("memset msg fail\n");
1092
1093 ret = memset_s(&rsp, sizeof(rsp), 0, sizeof(rsp));
1094 if (ret != TEE_SUCCESS)
1095 tlogw("memset rsp fail\n");
1096
1097 ret = ssa_receive_msg(OS_WAIT_FOREVER, (uint32_t *)(&cmd),
1098 (uint8_t *)&msg, sizeof(union ssa_agent_msg), &sndr);
1099 if (ret != TEE_SUCCESS) {
1100 tloge("get msg failed 0x%x\n", ret);
1101 continue;
1102 }
1103
1104 tlogd("-- SS Agent cmd: 0x%x from 0x%x\n", cmd, sndr);
1105
1106 ret = set_ssa_caller_info(sndr, cmd);
1107 if (ret != TEE_SUCCESS) {
1108 tloge("set_ssa_caller_info fail, ret:0x%x", ret);
1109 continue;
1110 }
1111
1112 ssa_cmd_proc(cmd, sndr, &msg);
1113 }
1114 tloge("Must not be here, ssa is close\n");
1115 }
1116
tee_task_entry(int32_t init_build)1117 __attribute__((visibility("default"))) void tee_task_entry(int32_t init_build)
1118 {
1119 uint32_t res_code;
1120
1121 task_entry_init(init_build);
1122
1123 tlogd("global_handle = 0x%x\n", g_global_handle);
1124
1125 res_code = ipc_hunt_by_name(SSA_SERVICE_NAME, &g_ssagent_handle);
1126 if (res_code != 0) {
1127 tloge("hunt by ssa error 0x%x\n", res_code);
1128 return;
1129 }
1130 tlogd("ssaHandle = 0x%x\n", g_ssagent_handle);
1131 ssa_handle_msg(NULL);
1132 }
1133