• 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 <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