• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "tc_client_driver.h"
33 #include "agent.h"
34 #include "gp_ops.h"
35 #include "mailbox_mempool.h"
36 #include "mem.h"
37 #include "smc.h"
38 #include "tc_client_sub_driver.h"
39 #include "tc_ns_log.h"
40 #include "teek_client_constants.h"
41 #include "teek_client_type.h"
42 #include "tz_spi_notify.h"
43 #include "tzdebug.h"
44 #include "tzdriver_compat.h"
45 
46 struct workqueue_struct *g_tzdriverWq = NULL;
47 
48 #define TEEC_PARAM_TYPES(param0_type, param1_type, param2_type, param3_type) \
49     (((param3_type) << 12) | ((param2_type) << 8) | \
50     ((param1_type) << 4) | (param0_type))
51 
52 #define TEEC_PARAM_TYPE_GET(paramTypes, index) \
53     (((paramTypes) >> ((index) << 2)) & 0x0F)
54 
55 // record device_file count
56 static unsigned int g_deviceFileCnt = 1;
57 static DEFINE_MUTEX(g_deviceFileCntLock);
58 
59 static LosTaskCB *g_teecdTask = NULL;
60 // dev node list and itself has mutex to avoid race
61 struct TcNsDevList g_tcNsDevList;
62 
63 // record all service node and need mutex to avoid race
64 struct list_head g_serviceList;
65 DEFINE_MUTEX(g_serviceListLock);
66 
67 #define TEECD_CERT_INDEX 0
68 // teecd must set 0 in g_arrayCertNativeVendor
69 static const unsigned char g_arrayCertNativeVendor[][SHA256_DIGEST_LENGTH] = {
70     /* /vendor/bin/teecd0 */
71     {0x99, 0xa2, 0xf1, 0xb3, 0xa3, 0x5f, 0x3f, 0x11, 0x8b, 0x33, 0xc1, 0x7e, 0xb9, 0xe8, 0x53, 0xbe,
72      0x88, 0xf0, 0xc4, 0x6a, 0xf2, 0x7e, 0x72, 0x6e, 0x91, 0xb7, 0x59, 0xf0, 0x73, 0x9c, 0x93, 0xa5},
73 
74     /* /vendor/bin/teec_hello0 */
75     {0x9a, 0xab, 0xac, 0x19, 0xaa, 0xb2, 0xeb, 0xf4, 0x99, 0x11, 0x94, 0x15, 0xee, 0xb0, 0x03, 0x09,
76      0xd6, 0xe8, 0xfe, 0xe9, 0x32, 0x37, 0x48, 0xfd, 0x2b, 0xf2, 0x2c, 0x78, 0x74, 0xd6, 0xc3, 0x9c},
77 
78     /* /vendor/bin/tee_test_mem0 */
79     {0x44, 0x7c, 0x8f, 0xc2, 0xa1, 0x1e, 0xfd, 0xab, 0x21, 0x63, 0x0e, 0xf8, 0x7d, 0x0b, 0xce, 0x06,
80      0x05, 0x7f, 0x4a, 0xa8, 0x14, 0x17, 0x0f, 0xef, 0xa6, 0xa5, 0x77, 0x6c, 0xfe, 0xca, 0x4a, 0x8e},
81 
82     /* /vendor/bin/tee_test_sess0 */
83     {0xa0, 0xe4, 0x1b, 0x61, 0x8c, 0xd5, 0xf4, 0x4c, 0xec, 0x29, 0x03, 0xcd, 0x2f, 0xce, 0x28, 0xa7,
84      0x67, 0xba, 0x3a, 0x10, 0x20, 0xd7, 0x95, 0x2b, 0x41, 0xaf, 0x47, 0x7c, 0x3d, 0xed, 0xce, 0xa4},
85 
86     /* /vendor/bin/tee_test_invoke0 */
87     {0xb5, 0x4e, 0x9d, 0x7b, 0x42, 0x10, 0x63, 0xcc, 0x4b, 0x7b, 0x16, 0x7d, 0xf6, 0xfe, 0xa8, 0x8e,
88      0x6f, 0xca, 0x1b, 0xf1, 0x6a, 0xff, 0xed, 0xfd, 0xee, 0x09, 0xed, 0xbb, 0x18, 0x13, 0x75, 0x02},
89 
90     /* /vendor/bin/tee_test_ut0 */
91     {0x45, 0x71, 0xd9, 0x4b, 0x5b, 0xc7, 0xc1, 0x29, 0x2f, 0x9f, 0x46, 0xf2, 0x92, 0xef, 0xd5, 0x44,
92      0xda, 0xb4, 0x51, 0xfb, 0x75, 0xa4, 0xc7, 0x4f, 0x8d, 0x34, 0xca, 0x5e, 0x27, 0xa6, 0x08, 0x8c},
93 
94     /* /vendor/bin/tee_test_ca0 */
95     {0xe9, 0x16, 0xde, 0x3f, 0x62, 0x27, 0x5b, 0x12, 0x04, 0x39, 0x9c, 0xc9, 0xf0, 0x34, 0x1f, 0xee,
96      0xf0, 0x1a, 0x66, 0x31, 0xa9, 0xbf, 0x7d, 0x14, 0x30, 0x3d, 0xae, 0xe1, 0xb3, 0x07, 0xb9, 0x54},
97 
98     /* /vendor/bin/tee_test_agent0 */
99     {0x20, 0x6f, 0x1c, 0x54, 0xd5, 0x5f, 0xa8, 0xa8, 0x88, 0x56, 0xc4, 0x0c, 0xc3, 0xf9, 0x9c, 0x9a,
100      0xc3, 0x40, 0x86, 0x13, 0x61, 0xb0, 0xcf, 0x69, 0xdd, 0xb8, 0x6c, 0x1e, 0x53, 0xb4, 0x77, 0x55},
101 
102     /* /vendor/bin/tee_test_client_api0 */
103     {0xae, 0xe9, 0x12, 0x90, 0x23, 0x9b, 0x99, 0x01, 0x99, 0x1d, 0xa5, 0x22, 0xe0, 0x26, 0x06, 0x12,
104      0x2b, 0xad, 0x5e, 0xaf, 0x34, 0xbf, 0x1a, 0x16, 0x3e, 0x75, 0x97, 0x65, 0xe6, 0x39, 0x9d, 0xf3},
105 };
106 
107 typedef struct {
108     TcNsDevFile *devFile;
109     char *fileBuffer;
110     unsigned int fileSize;
111 } LoadImageParams;
112 
GetServiceListLock(void)113 mutex_t *GetServiceListLock(void)
114 {
115     return &g_serviceListLock;
116 }
117 
GetTcNsDevList(void)118 struct TcNsDevList *GetTcNsDevList(void)
119 {
120     return &g_tcNsDevList;
121 }
122 
GetServiceList(void)123 struct list_head *GetServiceList(void)
124 {
125     return &g_serviceList;
126 }
127 
GetMemSpace(char ** caCert,char ** tpath)128 static int GetMemSpace(char **caCert, char **tpath)
129 {
130     *tpath = malloc(MAX_PATH_SIZE);
131     if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*tpath))) {
132         tloge("tpath malloc fail\n");
133         return -EPERM;
134     }
135     *caCert = malloc(BUF_MAX_SIZE);
136     if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*caCert))) {
137         tloge("caCert malloc fail\n");
138         free(*tpath);
139         *tpath = NULL;
140         return -EPERM;
141     }
142     return 0;
143 }
144 
CheckPathAndAccess(LosTaskCB * caTask,char * caCert,unsigned long messageSize,unsigned char * digest,unsigned int digLen)145 static int CheckPathAndAccess(LosTaskCB *caTask,
146     char *caCert, unsigned long messageSize,
147     unsigned char *digest, unsigned int digLen)
148 {
149     int ret;
150     unsigned long index;
151 
152     if (digLen != SHA256_DIGEST_LENGTH) {
153         tlogd("check process path digest len error\n");
154         return CHECK_PATH_HASH_FAIL;
155     }
156 
157     ret = CalcProcessPathHash((unsigned char *)caCert, messageSize, digest, digLen);
158     if (ret != 0) {
159         return ret;
160     }
161 
162     for (index = 0; index < (sizeof(g_arrayCertNativeVendor) / SHA256_DIGEST_LENGTH); index++) {
163         ret = memcmp(digest, g_arrayCertNativeVendor[index], digLen);
164         if (ret == 0) {
165             if (g_teecdTask == NULL && index == TEECD_CERT_INDEX) {
166                 g_teecdTask = GetProcessGroupLeader(caTask);
167             }
168             return 0;
169         }
170     }
171     return CHECK_PATH_HASH_FAIL;
172 }
173 
CheckProcessAccess(LosTaskCB * caTask)174 static int CheckProcessAccess(LosTaskCB *caTask)
175 {
176     char *caCert = NULL;
177     char *path = NULL;
178     char *tpath = NULL;
179     unsigned char digest[SHA256_DIGEST_LENTH] = {0};
180     int messageSize;
181     int ret;
182 
183     if (caTask == NULL) {
184         tloge("task_struct is NULL\n");
185         return -EPERM;
186     }
187 
188     if (IsKernelThread(caTask)) {
189         tlogd("kernel thread need not check\n");
190         ret = ENTER_BYPASS_CHANNEL;
191         return ret;
192     }
193 
194     ret = GetMemSpace(&caCert, &tpath);
195     if (ret != 0) {
196         return ret;
197     }
198 
199     path = GetProcessPath(caTask, tpath, MAX_PATH_SIZE);
200     if (!IS_ERR_OR_NULL(path)) {
201         errno_t sret;
202 
203         sret = memset_s(caCert, BUF_MAX_SIZE, 0x00, BUF_MAX_SIZE);
204         if (sret != EOK) {
205             tloge("memset error sret is %d\n", sret);
206             free(tpath);
207             free(caCert);
208             return -EPERM;
209         }
210 
211         messageSize = PackCaCert(caCert, path, caTask, GetTaskUid(caTask));
212         if (messageSize > 0) {
213             ret = CheckPathAndAccess(caTask, caCert,
214                 (unsigned long)messageSize, digest,
215                 (unsigned int)SHA256_DIGEST_LENTH);
216         } else {
217             ret = -EPERM;
218         }
219     } else {
220         ret = -EPERM;
221     }
222     free(tpath);
223     free(caCert);
224     return ret;
225 }
226 
227 /* Calculate the SHA256 file digest */
TeeCalcTaskHash(unsigned char * digest,uint32_t digLen,LosTaskCB * curStruct)228 static int TeeCalcTaskHash(unsigned char *digest,
229     uint32_t digLen, LosTaskCB *curStruct)
230 {
231     TeeSha256Context ctx;
232     LosVmSpace *space = OS_PCB_FROM_PID(curStruct->processID)->vmSpace;
233     if (space == NULL) {
234         return -EFAULT;
235     }
236 
237     TeeSha256Init(&ctx);
238     /* search the region list */
239     if (space->codeStart != 0 && space->codeEnd > space->codeStart) {
240         TeeSha256Update(&ctx, (void *)space->codeStart, space->codeEnd - space->codeStart);
241     } else {
242         return -EFAULT;
243     }
244     TeeSha256Final(&ctx, digest);
245     return 0;
246 }
247 
248 #define LIBTEEC_CODE_PAGE_SIZE 8
249 #define DEFAULT_TEXT_OFF 0
250 #define LIBTEEC_NAME_MAX_LEN 50
251 
252 #define LIBTEEC_SO "/vendor/lib/libteec_vendor.so"
253 
254 /* Calculate the SHA256 library digest */
TeeCalcTaskSoHash(unsigned char * digest,uint32_t digLen,LosTaskCB * curStruct,int soIndex)255 static int TeeCalcTaskSoHash(unsigned char *digest, uint32_t digLen,
256     LosTaskCB *curStruct, int soIndex)
257 {
258     TeeSha256Context ctx;
259     int findFlag = 0;
260     LosRbNode *pstRbNode = NULL;
261     LosRbNode *pstRbNodeNext = NULL;
262     LosVmSpace *space = OS_PCB_FROM_PID(curStruct->processID)->vmSpace;
263     if (space == NULL) {
264         return -EFAULT;
265     }
266 
267     TeeSha256Init(&ctx);
268     /* search the region list */
269     (VOID)LOS_MuxAcquire(&space->regionMux);
270     RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
271         LosVmMapRegion *region = (LosVmMapRegion *)pstRbNode;
272         if (!LOS_IsRegionFileValid(region)) {
273             continue;
274         }
275         struct Vnode *vnode = region->unTypeData.rf.vnode;
276         if (vnode != NULL && !strncmp(vnode->filePath, LIBTEEC_SO, strlen(LIBTEEC_SO))) {
277             TeeSha256Update(&ctx, (void *)region->range.base, region->range.size);
278             findFlag = 1;
279             break;
280         }
281     RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
282     (VOID)LOS_MuxRelease(&space->regionMux);
283 
284     if (findFlag == 0) {
285         return -EFAULT;
286     }
287     TeeSha256Final(&ctx, digest);
288     return 0;
289 }
290 
291 /* Modify the client context so params id 2 and 3 contain temp pointers to the
292  * public key and package name for the open session. This is used for the
293  * TEEC_LOGIN_IDENTIFY open session method
294  */
SetLoginInformation(TcNsDevFile * devFile,TcNsClientContext * context)295 static int SetLoginInformation(TcNsDevFile *devFile,
296     TcNsClientContext *context)
297 {
298     /* The daemon has failed to get login information or not supplied */
299     if (devFile->pkgNameLen == 0) {
300         return -1;
301     }
302     /* The 3rd parameter buffer points to the pkg name buffer in the
303      * device file pointer
304      * get package name len and package name
305      */
306     context->params[TEE_PARAM_FOUR].memref.sizeAddr =
307         (uintptr_t)&devFile->pkgNameLen;
308     context->params[TEE_PARAM_FOUR].memref.buffer =
309         (uintptr_t)devFile->PkgName;
310     /* Set public key len and public key */
311     if (devFile->pubKeyLen != 0) {
312         context->params[TEE_PARAM_THREE].memref.sizeAddr =
313             (uintptr_t)&devFile->pubKeyLen;
314         context->params[TEE_PARAM_THREE].memref.buffer =
315             (uintptr_t)devFile->pubKey;
316     } else {
317         /* If get public key failed, then get uid in kernel */
318         uint32_t caUid = TcNsGetUid();
319         if (caUid == (uint32_t)(-1)) {
320             tloge("Failed to get uid of the task\n");
321             goto error;
322         }
323 
324         devFile->pubKeyLen = sizeof(caUid);
325         context->params[TEE_PARAM_THREE].memref.sizeAddr =
326             (uintptr_t)&devFile->pubKeyLen;
327         if (memcpy_s(devFile->pubKey, MAX_PUBKEY_LEN, &caUid,
328             devFile->pubKeyLen)) {
329             tloge("Failed to copy pubkey, pubKeyLen=%u\n",
330                   devFile->pubKeyLen);
331             goto error;
332         }
333         context->params[TEE_PARAM_THREE].memref.buffer =
334             (uint64_t)(uintptr_t)devFile->pubKey;
335     }
336     /* Now we mark the 2 parameters as input temp buffers */
337     context->paramTypes = TEEC_PARAM_TYPES(
338         TEEC_PARAM_TYPE_GET(context->paramTypes, TEE_PARAM_ONE),
339         TEEC_PARAM_TYPE_GET(context->paramTypes, TEE_PARAM_TWO),
340         TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT);
341     return 0;
342 error:
343     return -1;
344 }
345 
CheckProcessAndAllocParams(TcNsDevFile * devFile,uint8_t ** certBuffer,unsigned int * certBufferSize)346 static int CheckProcessAndAllocParams(TcNsDevFile *devFile,
347     uint8_t **certBuffer, unsigned int *certBufferSize)
348 {
349     int ret;
350 
351 #ifdef SECURITY_AUTH_ENHANCE
352     ret = CheckProcessAccess(OsCurrTaskGet());
353     if (ret) {
354         tloge(KERN_ERR "tc client login: teecd verification failed ret 0x%x!\n", ret);
355         return -EPERM;
356     }
357 #endif
358     mutex_lock(&devFile->LoginSetupLock);
359     if (devFile->loginSetup) {
360         tloge("Login information cannot be set twice!\n");
361         mutex_unlock(&devFile->LoginSetupLock);
362         return -EINVAL;
363     }
364     devFile->loginSetup = true;
365     mutex_unlock(&devFile->LoginSetupLock);
366 
367     unsigned int bufSize = (unsigned int)(MAX_PACKAGE_NAME_LEN + MAX_PUBKEY_LEN +
368         sizeof(devFile->pkgNameLen) + sizeof(devFile->pubKeyLen));
369     *certBuffer = malloc(bufSize);
370     if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*certBuffer))) {
371         tloge("Failed to allocate login buffer!");
372         return -EFAULT;
373     }
374     *certBufferSize = bufSize;
375 
376     return 0;
377 }
378 
TcNsGetTeeVersion(const TcNsDevFile * devFile,void * argp)379 static int TcNsGetTeeVersion(const TcNsDevFile *devFile, void *argp)
380 {
381     unsigned int version;
382     TcNsSmcCmd smcCmd = { {0}, 0 };
383     int smcRet;
384     struct MbCmdPack *mbPack = NULL;
385 
386     if (argp == NULL || devFile == NULL) {
387         tloge("error input parameter\n");
388         return -1;
389     }
390     mbPack = MailboxAllocCmdPack();
391     if (mbPack == NULL) {
392         tloge("alloc mb pack failed\n");
393         return -ENOMEM;
394     }
395 
396     mbPack->operation.paramTypes = TEEC_VALUE_OUTPUT;
397     smcCmd.globalCmd = true;
398     smcCmd.cmdId = GLOBAL_CMD_ID_GET_TEE_VERSION;
399     smcCmd.devFileId = devFile->devFileId;
400     smcCmd.operationPhys = LOS_PaddrQuery(&mbPack->operation);
401     smcCmd.operationHphys = 0;
402     smcRet = TcNsSmc(&smcCmd);
403     if (smcRet != 0) {
404         tloge("smc_call returns error ret 0x%x\n", smcRet);
405     }
406 
407     version = mbPack->operation.params[0].value.a;
408     if (copy_to_user(argp, &version, sizeof(unsigned int))) {
409         if (smcRet != 0) {
410             smcRet = -EFAULT;
411         }
412     }
413     MailboxFree(mbPack);
414     return smcRet;
415 }
416 
417 #define MAX_BUF_LEN 4096
418 
TcNsClientLogWithoutCert(TcNsDevFile * devFile)419 static int TcNsClientLogWithoutCert(TcNsDevFile *devFile)
420 {
421     int ret;
422     uint8_t *certBuffer = NULL;
423     uint8_t *tempCertBuffer = NULL;
424     errno_t sret;
425     unsigned int certBufferSize = 0;
426     char *path = NULL;
427 
428     ret = CheckProcessAndAllocParams(devFile, &certBuffer,
429         &certBufferSize);
430     if (ret != 0) {
431         return ret;
432     }
433     tempCertBuffer = certBuffer;
434 
435     path = GetProcessPath(OsCurrTaskGet(), (char *)certBuffer, MAX_PACKAGE_NAME_LEN);
436     if (path == NULL) {
437         goto error;
438     }
439     devFile->pkgNameLen = strlen(path);
440 
441     sret = strncpy_s((char *)devFile->PkgName, MAX_PACKAGE_NAME_LEN, (char *)certBuffer,
442         devFile->pkgNameLen);
443     if (sret != EOK) {
444         ret = -ENOMEM;
445         goto error;
446     }
447     int uid = GetTaskUid(OsCurrTaskGet());
448     devFile->pubKeyLen = sizeof(uid);
449     if (memcpy_s((char *)devFile->pubKey, MAX_PUBKEY_LEN, (char *)&uid,
450         devFile->pubKeyLen)) {
451         tloge("Failed to copy cert, pubKeyLen=%u\n",
452             devFile->pubKeyLen);
453         ret = -EINVAL;
454         goto error;
455     }
456 error:
457     free(tempCertBuffer);
458     return ret;
459 }
460 
TcNsClientLogWithCert(TcNsDevFile * devFile,const void * buffer)461 static int TcNsClientLogWithCert(TcNsDevFile *devFile, const void *buffer)
462 {
463     int ret;
464     uint8_t *certBuffer = NULL;
465     uint8_t *tempCertBuffer = NULL;
466     errno_t sret;
467     unsigned int certBufferSize = 0;
468 
469     // application ca login
470     ret = CheckProcessAndAllocParams(devFile, &certBuffer,
471         &certBufferSize);
472     if (ret != 0) {
473         return ret;
474     }
475 
476     tempCertBuffer = certBuffer;
477     if (certBufferSize > MAX_BUF_LEN) {
478         tloge("cert buffer size is invalid!\n");
479         ret = -EINVAL;
480         goto error;
481     }
482 
483     if (copy_from_user(certBuffer, buffer, certBufferSize)) {
484         tloge("Failed to get user login info!\n");
485         ret = -EINVAL;
486         goto error;
487     }
488     /* get package name len */
489     ret = GetPackNameLen(devFile, certBuffer, certBufferSize);
490     if (ret != 0) {
491         goto error;
492     }
493     certBuffer += sizeof(devFile->pkgNameLen);
494 
495     /* get package name */
496     sret = strncpy_s((char *)devFile->PkgName, MAX_PACKAGE_NAME_LEN, (char *)certBuffer, devFile->pkgNameLen);
497     if (sret != EOK) {
498         ret = -ENOMEM;
499         goto error;
500     }
501     certBuffer += devFile->pkgNameLen;
502 
503     /* get public key len */
504     ret = GetPublicKeyLen(devFile, certBuffer, certBufferSize);
505     if (ret != 0) {
506         goto error;
507     }
508 
509     /* get public key */
510     if (devFile->pubKeyLen != 0) {
511         certBuffer += sizeof(devFile->pubKeyLen);
512         if (memcpy_s((char *)devFile->pubKey, MAX_PUBKEY_LEN, (char *)certBuffer, devFile->pubKeyLen)) {
513             tloge("Failed to copy cert, pubKeyLen=%u\n", devFile->pubKeyLen);
514             ret = -EINVAL;
515             goto error;
516         }
517         certBuffer += devFile->pubKeyLen;
518     }
519     ret = 0;
520 error:
521     free(tempCertBuffer);
522     return ret;
523 }
524 
TcNsClientLoginFunc(TcNsDevFile * devFile,const void * buffer)525 static int TcNsClientLoginFunc(TcNsDevFile *devFile,
526     const void *buffer)
527 {
528     if (buffer == NULL) {
529         return TcNsClientLogWithoutCert(devFile);
530     } else {
531         return TcNsClientLogWithCert(devFile, buffer);
532     }
533 }
534 
AllocForLoadImage(unsigned int * mbLoadSize,unsigned int fileSize,char ** mbLoadMem,struct MbCmdPack ** mbPack,TeecUuid ** uuidReturn)535 static int AllocForLoadImage(unsigned int *mbLoadSize,
536     unsigned int fileSize, char **mbLoadMem,
537     struct MbCmdPack **mbPack, TeecUuid **uuidReturn)
538 {
539     /* we will try any possible to alloc mailbox mem to load TA */
540     for (; *mbLoadSize > 0; *mbLoadSize >>= 1) {
541         *mbLoadMem = MailboxAlloc(*mbLoadSize, 0);
542         if (*mbLoadMem != NULL) {
543             break;
544         }
545         tlogw("alloc mem(size=%u) for TA load mem fail, will retry\n", *mbLoadSize);
546     }
547     if (*mbLoadMem == NULL) {
548         tloge("alloc TA load mem failed\n");
549         return -ENOMEM;
550     }
551     *mbPack = MailboxAllocCmdPack();
552     if (*mbPack == NULL) {
553         MailboxFree(*mbLoadMem);
554         *mbLoadMem = NULL;
555         tloge("alloc mb pack failed\n");
556         return -ENOMEM;
557     }
558     *uuidReturn = MailboxAlloc(sizeof(TeecUuid), 0);
559     if (*uuidReturn == NULL) {
560         MailboxFree(*mbLoadMem);
561         *mbLoadMem = NULL;
562         MailboxFree(*mbPack);
563         *mbPack = NULL;
564         tloge("alloc uuid failed\n");
565         return -ENOMEM;
566     }
567     return 0;
568 }
569 
PackDataForSmcCmd(uint32_t loadSize,const char * mbLoadMem,struct MbCmdPack * mbPack,TeecUuid * uuidReturn,TcNsSmcCmd * smcCmd)570 static void PackDataForSmcCmd(uint32_t loadSize,
571     const char *mbLoadMem, struct MbCmdPack *mbPack,
572     TeecUuid *uuidReturn, TcNsSmcCmd *smcCmd)
573 {
574     mbPack->operation.params[TEE_PARAM_ONE].memref.buffer =
575         LOS_PaddrQuery((void *)mbLoadMem);
576     mbPack->operation.bufferHaddr[TEE_PARAM_ONE] = 0;
577     mbPack->operation.params[TEE_PARAM_ONE].memref.size = loadSize + sizeof(int);
578     mbPack->operation.params[TEE_PARAM_THREE].memref.buffer =
579         LOS_PaddrQuery((void *)uuidReturn);
580     mbPack->operation.bufferHaddr[TEE_PARAM_THREE] = 0;
581     mbPack->operation.params[TEE_PARAM_THREE].memref.size = sizeof(*uuidReturn);
582     mbPack->operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT,
583         TEEC_VALUE_OUTPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_VALUE_INPUT);
584     /* load image smc command */
585     smcCmd->globalCmd = true;
586     smcCmd->cmdId = GLOBAL_CMD_ID_LOAD_SECURE_APP;
587     smcCmd->contextId = 0;
588     smcCmd->operationPhys = LOS_PaddrQuery(&mbPack->operation);
589     smcCmd->operationHphys = 0;
590 }
591 
592 struct MbLoad {
593     unsigned int mbLoadSize;
594     char *mbLoadMem;
595 };
596 
LoadImageByFrame(const LoadImageParams * paramsIn,struct MbLoad * mb,struct MbCmdPack * mbPack,TeecUuid * uuidReturn,unsigned int loadTimes)597 static int LoadImageByFrame(const LoadImageParams *paramsIn,
598     struct MbLoad *mb, struct MbCmdPack *mbPack, TeecUuid *uuidReturn,
599     unsigned int loadTimes)
600 {
601     char *p = mb->mbLoadMem;
602     uint32_t loadSize;
603     int loadFlag = 1; /* 0:it's last block, 1:not last block */
604     uint32_t loadedSize = 0;
605     unsigned int index;
606     TcNsSmcCmd smcCmd = { {0}, 0 };
607     int smcRet;
608 
609     for (index = 0; index < loadTimes; index++) {
610         if (index == (loadTimes - 1)) {
611             loadFlag = 0;
612             loadSize = paramsIn->fileSize - loadedSize;
613         } else {
614             loadSize = mb->mbLoadSize - sizeof(loadFlag);
615         }
616         *(int *)p = loadFlag;
617         if (loadSize > mb->mbLoadSize - sizeof(loadFlag)) {
618             tloge("invalid load size %u/%u\n", loadSize,
619                 mb->mbLoadSize);
620             return  -1;
621         }
622         if (copy_from_user(mb->mbLoadMem + sizeof(loadFlag),
623             (void __user *)(paramsIn->fileBuffer +
624             loadedSize), loadSize)) {
625             tloge("file buf get fail\n");
626             return  -1;
627         }
628         PackDataForSmcCmd(loadSize, mb->mbLoadMem, mbPack,
629             uuidReturn, &smcCmd);
630         mbPack->operation.params[TEE_PARAM_FOUR].value.a = index;
631         smcCmd.devFileId = paramsIn->devFile->devFileId;
632         smcRet = TcNsSmc(&smcCmd);
633         tlogd("smc cmd ret %d\n", smcRet);
634         tlogd("configid=%u, ret=%d, loadFlag=%d, index=%u\n",
635             mbPack->operation.params[1].value.a, smcRet,
636             loadFlag, index);
637 
638         if (smcRet != 0) {
639             tloge("smc_call returns error ret 0x%x\n", smcRet);
640             return -1;
641         }
642 
643         loadedSize += loadSize;
644     }
645     return 0;
646 }
647 
TcNsLoadImage(TcNsDevFile * devFile,char * fileBuffer,unsigned int fileSize)648 int TcNsLoadImage(TcNsDevFile *devFile, char *fileBuffer,
649     unsigned int fileSize)
650 {
651     int ret;
652     struct MbCmdPack *mbPack = NULL;
653     unsigned int mbLoadSize;
654     char *mbLoadMem = NULL;
655     TeecUuid *uuidReturn = NULL;
656     unsigned int loadTimes;
657     LoadImageParams paramsIn = {devFile, fileBuffer, fileSize};
658     bool checkValue = false;
659 
660     checkValue = (devFile == NULL || fileBuffer == NULL);
661     if (checkValue) {
662         tloge("devFile or fileBuffer is NULL!\n");
663         return -EINVAL;
664     }
665     if (!IsValidTaSize(fileBuffer, fileSize)) {
666         return -EINVAL;
667     }
668 
669     mbLoadSize = (fileSize > (SZ_1M - sizeof(int))) ? SZ_1M : ALIGN(fileSize, SZ_4K);
670 
671     ret = AllocForLoadImage(&mbLoadSize, fileSize, &mbLoadMem,
672         &mbPack, &uuidReturn);
673     if (ret != 0) {
674         return ret;
675     }
676 
677     if (mbLoadSize <= sizeof(int)) {
678         tloge("mbLoadSize is too small!\n");
679         ret = -ENOMEM;
680         goto FREE_MEM;
681     }
682 
683     loadTimes = fileSize / (mbLoadSize - sizeof(int));
684     if (fileSize % (mbLoadSize - sizeof(int))) {
685         loadTimes += 1;
686     }
687     struct MbLoad mb;
688     mb.mbLoadMem = mbLoadMem;
689     mb.mbLoadSize = mbLoadSize;
690     ret = LoadImageByFrame(&paramsIn, &mb, mbPack, uuidReturn, loadTimes);
691 FREE_MEM:
692     MailboxFree(mbLoadMem);
693     MailboxFree(mbPack);
694     MailboxFree(uuidReturn);
695     return ret;
696 }
697 
CheckTaskState(LosTaskCB ** halStruct,const TcNsClientContext * context)698 static int CheckTaskState(LosTaskCB **halStruct,
699     const TcNsClientContext *context)
700 {
701     bool checkValue = false;
702 
703     checkValue = (context->callingPid && !IsKernelThread(OsCurrTaskGet()));
704     if (checkValue == true) {
705         tloge("non hal service pass non-zero callingpid , reject please!!!\n");
706         return -EFAULT;
707     }
708     return 0;
709 }
710 
CalcTaskHash(uint8_t kernelApi,TcNsSession * session,TcNsService * service,LosTaskCB * curStruct)711 static int CalcTaskHash(uint8_t kernelApi,
712     TcNsSession *session, TcNsService *service,
713     LosTaskCB *curStruct)
714 {
715     int rc, i;
716     int soFound = 0;
717     if (kernelApi == TEE_REQ_FROM_USER_MODE) {
718         for (i = 0; soFound < NUM_OF_SO && i < KIND_OF_SO; i++) {
719             rc = TeeCalcTaskSoHash(session->authHashBuf + MAX_SHA_256_SZ * soFound,
720                 (uint32_t)SHA256_DIGEST_LENTH, curStruct, i);
721             if (rc == 0) {
722                 soFound++;
723             }
724         }
725         if (soFound != NUM_OF_SO) {
726             tlogd("so library found: %d\n", soFound);
727         }
728     } else {
729         tlogd("request from kernel\n");
730     }
731 
732 #ifdef CONFIG_ASAN_DEBUG
733     tloge("so auth disabled for ASAN debug\n");
734     uint32_t soHashLen = MAX_SHA_256_SZ * NUM_OF_SO;
735     errno_t sret = memset_s(session->authHashBuf, soHashLen, 0, soHashLen);
736     if (sret != EOK) {
737         tloge("memset so hash failed\n");
738         return -EFAULT;
739     }
740 #endif
741     rc = TeeCalcTaskHash(session->authHashBuf + MAX_SHA_256_SZ * NUM_OF_SO,
742         (uint32_t)SHA256_DIGEST_LENTH, curStruct);
743     if (rc != 0) {
744         tloge("tee calc ca hash failed\n");
745         return -EFAULT;
746     }
747     return 0;
748 }
749 
CheckLoginMethod(TcNsDevFile * devFile,TcNsClientContext * context,uint8_t * flags)750 static int CheckLoginMethod(TcNsDevFile *devFile,
751     TcNsClientContext *context, uint8_t *flags)
752 {
753     bool checkValue = false;
754     int ret;
755 
756     if (devFile == NULL || context == NULL || flags == NULL) {
757         return -EFAULT;
758     }
759     if (context->login.method == TEEC_LOGIN_IDENTIFY) {
760         tlogd("login method is IDENTIFY\n");
761         /* Check if params 0 and 1 are valid */
762         checkValue = devFile->kernelApi == TEE_REQ_FROM_USER_MODE &&
763             (TcUserParamValid(context, (unsigned int)TEE_PARAM_ONE) ||
764             TcUserParamValid(context, (unsigned int)TEE_PARAM_TWO));
765         if (checkValue == true) {
766             return -EFAULT;
767         }
768         ret = SetLoginInformation(devFile, context);
769         if (ret != 0) {
770             tloge("SetLoginInformation failed ret =%d\n", ret);
771             return ret;
772         }
773         *flags |= TC_CALL_LOGIN;
774     } else {
775         tlogd("login method is not supported\n");
776         return -EINVAL;
777     }
778     return 0;
779 }
780 
FindService(TcNsDevFile * devFile,const TcNsClientContext * context)781 static TcNsService *FindService(TcNsDevFile *devFile,
782     const TcNsClientContext *context)
783 {
784     int ret;
785     TcNsService *service = NULL;
786     bool isNewService = false;
787     bool isFull = false;
788 
789     mutex_lock(&devFile->serviceLock);
790     service = TcRefServiceInDev(devFile, context->uuid,
791         UUID_LEN, &isFull);
792     /* if service has been opened in this dev or ref cnt is full */
793     if (service != NULL || isFull == true) {
794         /* If service has been reference by this dev, TcFindServiceInDev
795          * will increase a ref count to declaim there's how many callers to
796          * this service from the devFile, instead of increase service->usage.
797          * While close session, dev->serviceRef[i] will decrease and till
798          * it get to 0 PutServiceStruct will be called.
799          */
800         mutex_unlock(&devFile->serviceLock);
801         return service;
802     }
803     mutex_lock(&g_serviceListLock);
804     service = TcFindServiceFromAll(context->uuid, (uint32_t)UUID_LEN);
805     /* if service has been opened in other dev */
806     if (service != NULL) {
807         GetServiceStruct(service);
808         mutex_unlock(&g_serviceListLock);
809         goto ADD_SERVICE;
810     }
811     /* Create a new service if we couldn't find it in list */
812     ret = TcNsServiceInit(context->uuid, (uint32_t)UUID_LEN, &service);
813     /* Put unlock after TcNsServiceInit to make sure TcFindServiceFromAll * is correct */
814     mutex_unlock(&g_serviceListLock);
815     if (ret) {
816         tloge("service init failed");
817         mutex_unlock(&devFile->serviceLock);
818         return NULL;
819     }
820     isNewService = true;
821 ADD_SERVICE:
822     ret = AddServiceToDev(devFile, service);
823     mutex_unlock(&devFile->serviceLock);
824     if (ret) {
825         if (isNewService) {
826             PutServiceStruct(service);
827         }
828         service = NULL;
829         tloge("fail to add service to dev\n");
830         return NULL;
831     }
832     return service;
833 }
834 
ProcCalcTaskHash(TcNsDevFile * devFile,TcNsClientContext * context,TcNsSession * session,TcNsService * service,uint8_t * flags)835 static int ProcCalcTaskHash(TcNsDevFile *devFile,
836     TcNsClientContext *context, TcNsSession *session,
837     TcNsService *service, uint8_t *flags)
838 {
839     int ret;
840     LosTaskCB *curStruct = NULL;
841     LosTaskCB *halStruct = NULL;
842 
843     ret = CheckLoginMethod(devFile, context, flags);
844     if (ret != 0) {
845         return ret;
846     }
847     context->cmdId = GLOBAL_CMD_ID_OPEN_SESSION;
848     mutex_init(&session->taSessionLock);
849 
850     ret = CheckTaskState(&halStruct, context);
851     if (ret != 0) {
852         return ret;
853     }
854     if (halStruct != NULL) {
855         curStruct = halStruct;
856     } else {
857         curStruct = OsCurrTaskGet();
858     }
859     /* lock reason:
860      * TeeCalcTaskHash will use the global value g_tee_shash_tfm
861      */
862     ret = CalcTaskHash(devFile->kernelApi, session, service, curStruct);
863     return ret;
864 }
865 
ProcAfterSmcCmd(TcNsDevFile * devFile,const TcNsClientContext * context,TcNsService * service,TcNsSession * session)866 static void ProcAfterSmcCmd(TcNsDevFile *devFile,
867     const TcNsClientContext *context, TcNsService *service,
868     TcNsSession *session)
869 {
870     session->sessionId = context->sessionId;
871 #ifdef TC_ASYNC_NOTIFY_SUPPORT
872     session->waitData.sendWaitFlag = 0;
873     init_waitqueue_head(&session->waitData.sendCmdWq);
874 #endif
875     atomic_set(&session->usage, 1);
876     session->owner = devFile;
877     mutex_lock(&service->SessionLock);
878     list_add_tail(&session->head, &service->sessionList);
879     mutex_unlock(&service->SessionLock);
880 }
881 
ProcOpenSession(TcNsDevFile * devFile,TcNsClientContext * context,TcNsService * service,TcNsSession * session,uint8_t flags)882 static int ProcOpenSession(TcNsDevFile *devFile,
883     TcNsClientContext *context, TcNsService *service,
884     TcNsSession *session, uint8_t flags)
885 {
886     int ret;
887 
888     mutex_lock(&service->operationLock);
889     ret = LoadTaImage(devFile, context);
890     if (ret != 0) {
891         tloge("load ta image failed\n");
892         mutex_unlock(&service->operationLock);
893         return ret;
894     }
895     /* send smc */
896 #ifdef SECURITY_AUTH_ENHANCE
897     ret = GetSessionSecureParams(devFile, context, session);
898     if (ret) {
899         tloge("Get session secure parameters failed, ret = %d.\n", ret);
900         /* Clean this session secure information */
901         CleanSessionSecureInformation(session);
902         mutex_unlock(&service->operationLock);
903         return ret;
904     }
905     session->TcNsToken.tokenBuffer =
906         calloc(1, TOKEN_BUFFER_LEN);
907     session->TcNsToken.tokenLen = TOKEN_BUFFER_LEN;
908     if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)
909         session->TcNsToken.tokenBuffer)) {
910         tloge("calloc %d bytes token failed.\n", TOKEN_BUFFER_LEN);
911         /* Clean this session secure information */
912         CleanSessionSecureInformation(session);
913         mutex_unlock(&service->operationLock);
914         return -ENOMEM;
915     }
916     ret = TcClientCall(context, devFile, session, flags);
917     if (ret != 0) {
918         /* Clean this session secure information */
919         CleanSessionSecureInformation(session);
920     }
921 #else
922     ret = TcClientCall(context, devFile, session, flags);
923 #endif
924     if (ret != 0) {
925         mutex_unlock(&service->operationLock);
926         tloge("smc_call returns error, ret=0x%x\n", ret);
927         return ret;
928     }
929     ProcAfterSmcCmd(devFile, context, service, session);
930     /* sessionId in tee is unique, but in concurrency scene
931      * same sessionId may appear in tzdriver, put sessionList
932      * add/del in service->operationLock can avoid it.
933      */
934     mutex_unlock(&service->operationLock);
935     return ret;
936 }
937 
ProcErrorSituation(TcNsDevFile * devFile,TcNsClientContext * context,TcNsService * service,TcNsSession * session)938 static void ProcErrorSituation(TcNsDevFile *devFile,
939     TcNsClientContext *context, TcNsService *service,
940     TcNsSession *session)
941 {
942     ReleaseFreeSession(devFile, context, session);
943     mutex_lock(&devFile->serviceLock);
944     DelServiceFromDev(devFile, service);
945     mutex_unlock(&devFile->serviceLock);
946     free(session);
947     return;
948 }
949 
TcNsOpenSession(TcNsDevFile * devFile,TcNsClientContext * context)950 int TcNsOpenSession(TcNsDevFile *devFile,
951     TcNsClientContext *context)
952 {
953     int ret;
954     TcNsService *service = NULL;
955     TcNsSession *session = NULL;
956     uint8_t flags = TC_CALL_GLOBAL;
957     bool checkValue = (devFile == NULL || context == NULL);
958 
959     if (checkValue == true) {
960         tloge("invalid devFile or context\n");
961         return -EINVAL;
962     }
963 
964     ret = CheckProcessAccess(OsCurrTaskGet());
965     if (ret) {
966         tloge("tee driver fd may be leak\n");
967         return -EPERM;
968     }
969 
970     service = FindService(devFile, context);
971     if (service == NULL) {
972         tloge("find service failed\n");
973         return -ENOMEM;
974     }
975     session = calloc(1, sizeof(*session));
976     if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)session)) {
977         tloge("calloc failed\n");
978         mutex_lock(&devFile->serviceLock);
979         DelServiceFromDev(devFile, service);
980         mutex_unlock(&devFile->serviceLock);
981         return -ENOMEM;
982     }
983 
984     ret = ProcCalcTaskHash(devFile, context, session, service,
985         &flags);
986     if (ret != 0) {
987         goto error;
988     }
989     ret = ProcOpenSession(devFile, context, service, session, flags);
990     if (ret == 0) {
991         return ret;
992     }
993 error:
994     ProcErrorSituation(devFile, context, service, session);
995     return ret;
996 }
997 
GetService(TcNsDevFile * devFile,const TcNsClientContext * context)998 static TcNsService *GetService(TcNsDevFile *devFile,
999     const TcNsClientContext *context)
1000 {
1001     TcNsService *service = NULL;
1002 
1003     mutex_lock(&devFile->serviceLock);
1004     service = TcFindServiceInDev(devFile,
1005         context->uuid, UUID_LEN);
1006     GetServiceStruct(service);
1007     mutex_unlock(&devFile->serviceLock);
1008     return service;
1009 }
1010 
PutSessionStruct(struct TagTcNsSession * session)1011 void PutSessionStruct(struct TagTcNsSession *session)
1012 {
1013     if (session == NULL || !atomic_dec_and_test(&session->usage)) {
1014         return;
1015     }
1016 
1017 #ifdef SECURITY_AUTH_ENHANCE
1018     if (session->TcNsToken.tokenBuffer != NULL) {
1019         if (memset_s(
1020             (void *)session->TcNsToken.tokenBuffer,
1021             session->TcNsToken.tokenLen,
1022             0,
1023             session->TcNsToken.tokenLen) != EOK) {
1024             tloge("Caution, memset failed!\n");
1025         }
1026         free(session->TcNsToken.tokenBuffer);
1027         session->TcNsToken.tokenBuffer = NULL;
1028         (void)session->TcNsToken.tokenBuffer; /* avoid Codex warning */
1029     }
1030 #endif
1031     if (memset_s((void *)session, sizeof(*session), 0, sizeof(*session)) != EOK) {
1032         tloge("Caution, memset failed!\n");
1033     }
1034     free(session);
1035 }
1036 
GetSession(TcNsService * service,TcNsDevFile * devFile,const TcNsClientContext * context)1037 static TcNsSession *GetSession(TcNsService *service,
1038     TcNsDevFile *devFile, const TcNsClientContext *context)
1039 {
1040     TcNsSession *session = NULL;
1041 
1042     mutex_lock(&service->SessionLock);
1043     session = TcFindSessionWithOwner(&service->sessionList,
1044         context->sessionId, devFile);
1045     GetSessionStruct(session);
1046     mutex_unlock(&service->SessionLock);
1047     return session;
1048 }
1049 
GetServiceStruct(struct TagTcNsService * service)1050 void GetServiceStruct(struct TagTcNsService *service)
1051 {
1052     if (service != NULL) {
1053         atomic_inc(&service->usage);
1054         tlogd("service->usage = %d\n", atomic_read(&service->usage));
1055     }
1056 }
1057 
PutServiceStruct(struct TagTcNsService * service)1058 void PutServiceStruct(struct TagTcNsService *service)
1059 {
1060     if (service != NULL) {
1061         tlogd("service->usage = %d\n", atomic_read(&service->usage));
1062         mutex_lock(&g_serviceListLock);
1063         if (atomic_dec_and_test(&service->usage)) {
1064             tlogd("del service [0x%x] from service list\n",
1065                 *(uint32_t *)service->uuid);
1066             list_del(&service->head);
1067             free(service);
1068         }
1069         mutex_unlock(&g_serviceListLock);
1070     }
1071 }
1072 
TcNsCloseSession(TcNsDevFile * devFile,TcNsClientContext * context)1073 int TcNsCloseSession(TcNsDevFile *devFile,
1074     TcNsClientContext *context)
1075 {
1076     int ret = -EINVAL;
1077     errno_t ret_err;
1078     TcNsService *service = NULL;
1079     TcNsSession *session = NULL;
1080 
1081     if (devFile == NULL || context == NULL) {
1082         tloge("invalid devFile or context\n");
1083         return ret;
1084     }
1085     service = GetService(devFile, context);
1086     if (service == NULL) {
1087         tloge("invalid service\n");
1088         return ret;
1089     }
1090     /*
1091      * sessionId in tee is unique, but in concurrency scene
1092      * same sessionId may appear in tzdriver, put sessionList
1093      * add/del in service->operationLock can avoid it.
1094      */
1095     mutex_lock(&service->operationLock);
1096     session = GetSession(service, devFile, context);
1097     if (session != NULL) {
1098         int ret2;
1099         mutex_lock(&session->taSessionLock);
1100         ret2 = CloseSession(devFile, session, context->uuid,
1101             (unsigned int)UUID_LEN, context->sessionId);
1102         mutex_unlock(&session->taSessionLock);
1103         if (ret2 != TEEC_SUCCESS) {
1104             tloge("close session smc failed!\n");
1105         }
1106 #ifdef SECURITY_AUTH_ENHANCE
1107         /* Clean this session secure information */
1108         ret_err = memset_s((void *)&session->secureInfo,
1109             sizeof(session->secureInfo),
1110             0, sizeof(session->secureInfo));
1111         if (ret_err != EOK) {
1112             tloge("close session memset error=%d\n", ret_err);
1113         }
1114 #endif
1115         mutex_lock(&service->SessionLock);
1116         list_del(&session->head);
1117         mutex_unlock(&service->SessionLock);
1118 
1119         PutSessionStruct(session);
1120         PutSessionStruct(session); /* pair with open session */
1121 
1122         ret = TEEC_SUCCESS;
1123         mutex_lock(&devFile->serviceLock);
1124         DelServiceFromDev(devFile, service);
1125         mutex_unlock(&devFile->serviceLock);
1126     } else {
1127         tloge("invalid session\n");
1128     }
1129     mutex_unlock(&service->operationLock);
1130     PutServiceStruct(service);
1131     return ret;
1132 }
1133 
TcNsSendCmd(TcNsDevFile * devFile,TcNsClientContext * context)1134 int TcNsSendCmd(TcNsDevFile *devFile,
1135     TcNsClientContext *context)
1136 {
1137     int ret = -EINVAL;
1138     TcNsService *service = NULL;
1139     TcNsSession *session = NULL;
1140     bool checkValue = (devFile == NULL || context == NULL);
1141 
1142     if (checkValue == true) {
1143         tloge("invalid devFile or context\n");
1144         return ret;
1145     }
1146     tlogd("session id :%x\n", context->sessionId);
1147     service = GetService(devFile, context);
1148     /* check sessionid is validated or not */
1149     if (service != NULL) {
1150         session = GetSession(service, devFile, context);
1151         PutServiceStruct(service);
1152         if (session != NULL) {
1153             tlogd("send cmd find session id %x\n",
1154                 context->sessionId);
1155             goto FIND_SESSION;
1156         }
1157     } else {
1158         tloge("can't find service\n");
1159     }
1160     tloge("send cmd can not find session id %u\n", context->sessionId);
1161     return ret;
1162 FIND_SESSION:
1163     /* send smc */
1164     mutex_lock(&session->taSessionLock);
1165     ret = TcClientCall(context, devFile, session, 0);
1166     mutex_unlock(&session->taSessionLock);
1167     PutSessionStruct(session);
1168     if (ret != 0) {
1169         tloge("smc_call returns error, ret=0x%x\n", ret);
1170     }
1171     return ret;
1172 }
1173 
TcNsClientOpen(TcNsDevFile ** devFile,uint8_t kernelApi)1174 int TcNsClientOpen(TcNsDevFile **devFile, uint8_t kernelApi)
1175 {
1176     int ret = TEEC_ERROR_GENERIC;
1177     TcNsDevFile *dev = NULL;
1178 
1179     tlogd("TcClientOpen\n");
1180     if (devFile == NULL) {
1181         tloge("devFile is NULL\n");
1182         return -EFAULT;
1183     }
1184     dev = calloc(1, sizeof(*dev));
1185     if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)dev)) {
1186         tloge("dev malloc failed\n");
1187         return ret;
1188     }
1189     mutex_lock(&g_tcNsDevList.devLock);
1190     list_add_tail(&dev->head, &g_tcNsDevList.devFileList);
1191     mutex_unlock(&g_tcNsDevList.devLock);
1192     mutex_lock(&g_deviceFileCntLock);
1193     dev->devFileId = g_deviceFileCnt;
1194     g_deviceFileCnt++;
1195     mutex_unlock(&g_deviceFileCntLock);
1196     INIT_LIST_HEAD(&dev->sharedMemList);
1197     dev->loginSetup = 0;
1198     dev->kernelApi = kernelApi;
1199     dev->loadAppFlag = 0;
1200     mutex_init(&dev->serviceLock);
1201     mutex_init(&dev->sharedMemLock);
1202     mutex_init(&dev->LoginSetupLock);
1203     *devFile = dev;
1204     ret = TEEC_SUCCESS;
1205     return ret;
1206 }
1207 
FreeDev(TcNsDevFile * dev)1208 void FreeDev(TcNsDevFile *dev)
1209 {
1210     DelDevNode(dev);
1211     TeeAgentClearDevOwner(dev);
1212     if (memset_s((void *)dev, sizeof(*dev), 0, sizeof(*dev)) != EOK) {
1213         tloge("Caution, memset dev fail!\n");
1214     }
1215     free(dev);
1216 }
1217 
TcNsClientClose(TcNsDevFile * dev)1218 int TcNsClientClose(TcNsDevFile *dev)
1219 {
1220     int ret = TEEC_ERROR_GENERIC;
1221     uint32_t index;
1222 
1223     if (dev == NULL) {
1224         tloge("invalid dev(null)\n");
1225         return ret;
1226     }
1227 
1228     /* close unclosed session */
1229     for (index = 0; index < SERVICES_MAX_COUNT; index++) {
1230         CloseUnclosedSession(dev, index);
1231     }
1232 
1233     // for thirdparty agent, code runs here only when agent crashed
1234     SendCrashedEventResponseAll(dev);
1235     ret = TEEC_SUCCESS;
1236     FreeDev(dev);
1237     return ret;
1238 }
1239 
ReleaseVmaSharedMem(TcNsDevFile * devFile,const LosVmMapRegion * vma)1240 static void ReleaseVmaSharedMem(TcNsDevFile *devFile,
1241     const LosVmMapRegion *vma)
1242 {
1243     TcNsSharedMem *sharedMem = NULL;
1244     TcNsSharedMem *sharedMemTemp = NULL;
1245     bool find = false;
1246 
1247     mutex_lock(&devFile->sharedMemLock);
1248     list_for_each_entry_safe(sharedMem, sharedMemTemp,
1249         &devFile->sharedMemList, head) {
1250         if (sharedMem != NULL) {
1251             if (sharedMem->userAddr ==
1252                 (void *)(uintptr_t)vma->range.base) {
1253                 sharedMem->userAddr = NULL;
1254                 find = true;
1255             } else if (sharedMem->userAddrCa ==
1256                 (void *)(uintptr_t)vma->range.base) {
1257                 sharedMem->userAddrCa = NULL;
1258                 find = true;
1259             }
1260 
1261             if ((sharedMem->userAddr == NULL) &&
1262                 (sharedMem->userAddrCa == NULL)) {
1263                 list_del(&sharedMem->head);
1264             }
1265 
1266             /* pair with TcClientMmap */
1267             if (find == true) {
1268                 PutSharememStruct(sharedMem);
1269                 break;
1270             }
1271         }
1272     }
1273     mutex_unlock(&devFile->sharedMemLock);
1274 }
1275 
TcNsSharedMemUnmap(TcNsDevFile * devFile,const unsigned int argp)1276 static int TcNsSharedMemUnmap(TcNsDevFile *devFile, const unsigned int argp)
1277 {
1278     if (devFile == NULL) {
1279         tloge("unmap input error\n");
1280         return -EINVAL;
1281     }
1282 
1283     LosVmMapRegion *vma = LOS_RegionFind(OsCurrProcessGet()->vmSpace, (vaddr_t)argp);
1284     if (vma == NULL) {
1285         tloge("unmap error memory\n");
1286         return -EINVAL;
1287     }
1288 
1289     bool checkValue = (IsTeecdProcess(g_teecdTask, OsCurrTaskGet())) && (!TcNsGetUid()) &&
1290         ((g_teecdTask->taskStatus & OS_TASK_STATUS_EXIT) || (OsCurrTaskGet()->taskStatus & OS_TASK_STATUS_EXIT));
1291     if (checkValue == true) {
1292         tlogd("teecd is killed, just return in vma close\n");
1293         return 0;
1294     }
1295     ReleaseVmaSharedMem(devFile, vma);
1296     return 0;
1297 }
1298 
AllocAndFindSharedMem(const LosVmMapRegion * vma,TcNsDevFile * devFile,bool * onlyRemap)1299 static TcNsSharedMem *AllocAndFindSharedMem(const LosVmMapRegion *vma,
1300     TcNsDevFile *devFile, bool *onlyRemap)
1301 {
1302     TcNsSharedMem *shmTmp = NULL;
1303     unsigned long len = vma->range.size;
1304 
1305     /* using vma->vm_pgoff as share_mem index */
1306     /* check if aready allocated */
1307     list_for_each_entry(shmTmp, &devFile->sharedMemList, head) {
1308         if (atomic_read(&shmTmp->offset) == vma->pgOff) {
1309             tlogd("share_mem already allocated, shmTmp->offset=%d\n",
1310                 atomic_read(&shmTmp->offset));
1311             /* args check:
1312              * 1. this shared mem is already mapped ?
1313              * 2. remap a different size sharedMem ?
1314              */
1315             if (shmTmp->userAddrCa != NULL ||
1316                 vma->range.size != shmTmp->len) {
1317                 tloge("already remap once!\n");
1318                 return NULL;
1319             }
1320             /* return the same sharedmem specified by vma->vm_pgoff */
1321             *onlyRemap = true;
1322             GetSharememStruct(shmTmp);
1323             return shmTmp;
1324         }
1325     }
1326 
1327     /* if not find, alloc a new sharemem */
1328     return TcMemAllocate(len);
1329 }
1330 
RemapSharedMem(LosVmMapRegion * vma,TcNsSharedMem * sharedMem)1331 static int RemapSharedMem(LosVmMapRegion *vma, TcNsSharedMem *sharedMem)
1332 {
1333     int ret;
1334 
1335     ret = RemapVmallocRange(vma, sharedMem->kernelAddr, 0);
1336     if (ret) {
1337         tloge("can't remap to user, ret = %d\n", ret);
1338         return -1;
1339     }
1340     return ret;
1341 }
1342 
1343 /* in this func, we need to deal with follow cases:
1344  * vendor CA alloc sharedmem (alloc and remap);
1345  * HAL alloc sharedmem (alloc and remap);
1346  * system CA alloc sharedmem (only just remap);
1347  */
TcClientMmap(struct file * filp,LosVmMapRegion * vma)1348 static int TcClientMmap(struct file *filp, LosVmMapRegion *vma)
1349 {
1350     int ret;
1351     TcNsDevFile *devFile = NULL;
1352     TcNsSharedMem *sharedMem = NULL;
1353     bool onlyRemap = false;
1354     bool checkValue = false;
1355 
1356     checkValue = (filp == NULL || vma == NULL || filp->f_priv == NULL);
1357     if (checkValue == true) {
1358         tloge("invalid args for tc mmap\n");
1359         return -EINVAL;
1360     }
1361     devFile = filp->f_priv;
1362 
1363     mutex_lock(&devFile->sharedMemLock);
1364     sharedMem = AllocAndFindSharedMem(vma, devFile, &onlyRemap);
1365     if (IS_ERR_OR_NULL(sharedMem)) {
1366         tloge("alloc shared mem failed\n");
1367         mutex_unlock(&devFile->sharedMemLock);
1368         return -ENOMEM;
1369     }
1370 
1371     ret = RemapSharedMem(vma, sharedMem);
1372     if (ret != 0) {
1373         if (onlyRemap) {
1374             PutSharememStruct(sharedMem);
1375         } else {
1376             TcMemFree(sharedMem);
1377         }
1378         mutex_unlock(&devFile->sharedMemLock);
1379         return ret;
1380     }
1381 
1382     if (onlyRemap) {
1383         sharedMem->userAddrCa = (void *)vma->range.base;
1384         mutex_unlock(&devFile->sharedMemLock);
1385         return ret;
1386     }
1387     sharedMem->userAddr = (void *)vma->range.base;
1388     atomic_set(&sharedMem->offset, vma->pgOff);
1389     GetSharememStruct(sharedMem);
1390     list_add_tail(&sharedMem->head, &devFile->sharedMemList);
1391     mutex_unlock(&devFile->sharedMemLock);
1392     return ret;
1393 }
1394 
IoctlSessionSendCmd(TcNsDevFile * devFile,TcNsClientContext * context,void * argp)1395 static int IoctlSessionSendCmd(TcNsDevFile *devFile,
1396     TcNsClientContext *context, void *argp)
1397 {
1398     int ret;
1399 
1400     ret = TcNsSendCmd(devFile, context);
1401     if (ret) {
1402         tloge("TcNsSendCmd Failed ret is %d\n", ret);
1403     }
1404     if (copy_to_user(argp, context, sizeof(*context))) {
1405         if (ret == 0) {
1406             ret = -EFAULT;
1407         }
1408     }
1409     return ret;
1410 }
1411 
TcClientSessionIoctl(struct file * file,unsigned int cmd,unsigned long arg)1412 static int TcClientSessionIoctl(struct file *file, unsigned int cmd,
1413     unsigned long arg)
1414 {
1415     int ret = TEEC_ERROR_GENERIC;
1416     void *argp = (void __user *)(uintptr_t)arg;
1417     TcNsDevFile *devFile = file->f_priv;
1418     TcNsClientContext context;
1419 
1420     if (argp == NULL) {
1421         tloge("argp is NULL input buffer\n");
1422         ret = -EINVAL;
1423         return ret;
1424     }
1425     if (copy_from_user(&context, argp, sizeof(context))) {
1426         tloge("copy from user failed\n");
1427         return -EFAULT;
1428     }
1429     context.returns.origin = TEEC_ORIGIN_COMMS;
1430     switch (cmd) {
1431         case TC_NS_CLIENT_IOCTL_SES_OPEN_REQ: {
1432             ret = TcNsOpenSession(devFile, &context);
1433             if (ret) {
1434                 tloge("TcNsOpenSession Failed ret is %d\n", ret);
1435             }
1436             if (copy_to_user(argp, &context, sizeof(context)) && ret == 0) {
1437                 ret = -EFAULT;
1438             }
1439             break;
1440         }
1441         case TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ: {
1442             ret = TcNsCloseSession(devFile, &context);
1443             break;
1444         }
1445         case TC_NS_CLIENT_IOCTL_SEND_CMD_REQ: {
1446             ret = IoctlSessionSendCmd(devFile, &context, argp);
1447             break;
1448         }
1449         default:
1450             tloge("invalid cmd:0x%x!\n", cmd);
1451             return ret;
1452     }
1453     /*
1454      * Don't leak ERESTARTSYS to user space.
1455      *
1456      * CloseSession is not reentrant, so convert to -EINTR.
1457      * In other case, RestartSyscall().
1458      *
1459      * It is better to call it right after the error code
1460      * is generated (in TcClientCall), but kernel CAs are
1461      * still exist when these words are written. Setting TIF
1462      * flags for callers of those CAs is very hard to analysis.
1463      *
1464      * For kernel CA, when ERESTARTSYS is seen, loop in kernel
1465      * instead of notifying user.
1466      *
1467      * P.S. ret code in this function is in mixed naming space.
1468      * See the definition of ret. However, this function never
1469      * return its default value, so using -EXXX is safe.
1470      */
1471     if (ret == -ERESTARTSYS) {
1472         if (cmd == TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ) {
1473             ret = -EINTR;
1474         } else {
1475             return RestartSyscall();
1476         }
1477     }
1478     return ret;
1479 }
1480 
IoctlRegisterAgent(TcNsDevFile * devFile,unsigned long arg)1481 static int IoctlRegisterAgent(TcNsDevFile *devFile, unsigned long arg)
1482 {
1483     int ret;
1484     struct AgentIoctlArgs args;
1485 
1486     if (copy_from_user(&args, (void *)arg, sizeof(args))) {
1487         tloge("copy agent args failed\n");
1488         return -EFAULT;
1489     }
1490 
1491     ret = TcNsRegisterAgent(devFile, args.id, args.bufferSize,
1492         &args.buffer, true);
1493     if (ret == 0) {
1494         if (copy_to_user((void *)arg, &args, sizeof(args))) {
1495             tloge("copy agent user addr failed\n");
1496         }
1497     }
1498 
1499     return ret;
1500 }
1501 
IoctlUnregisterAgent(const TcNsDevFile * devFile,unsigned long arg)1502 static int IoctlUnregisterAgent(const TcNsDevFile *devFile, unsigned long arg)
1503 {
1504     int ret;
1505     struct SmcEventData *eventData = NULL;
1506     eventData = FindEventControl((unsigned int)arg);
1507     if (eventData == NULL) {
1508         tloge("invalid agent id\n");
1509         return TEEC_ERROR_GENERIC;
1510     }
1511     if (eventData->owner != devFile) {
1512         tloge("invalid unregister request\n");
1513         PutAgentEvent(eventData);
1514         return TEEC_ERROR_GENERIC;
1515     }
1516     PutAgentEvent(eventData);
1517     ret = TcNsUnregisterAgent((unsigned int)arg);
1518     return ret;
1519 }
1520 
TcAgentIoctl(struct file * file,unsigned int cmd,unsigned long arg)1521 static long TcAgentIoctl(struct file *file, unsigned int cmd, unsigned long arg)
1522 {
1523     int ret = TEEC_ERROR_GENERIC;
1524     TcNsDevFile *devFile = file->f_priv;
1525 
1526     if (devFile == NULL) {
1527         tloge("invalid params\n");
1528         return ret;
1529     }
1530     switch (cmd) {
1531         case TC_NS_CLIENT_IOCTL_WAIT_EVENT: {
1532             ret = TcNsWaitEvent((unsigned int)arg);
1533             break;
1534         }
1535         case TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE: {
1536             ret = TcNsSendEventResponse((unsigned int)arg);
1537             break;
1538         }
1539         case TC_NS_CLIENT_IOCTL_REGISTER_AGENT: {
1540             ret = IoctlRegisterAgent(devFile, arg);
1541             break;
1542         }
1543         case TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT: {
1544             ret = IoctlUnregisterAgent(devFile, arg);
1545             break;
1546         }
1547         case TC_NS_CLIENT_IOCTL_SYC_SYS_TIME: {
1548             ret = TcNsSyncSysTime((TcNsClientTime *)(uintptr_t)arg);
1549             break;
1550         }
1551         case TC_NS_CLIENT_IOCTL_SET_NATIVECA_IDENTITY: {
1552             ret = TcNsSetNativeHash(arg, GLOBAL_CMD_ID_SET_CA_HASH);
1553             break;
1554         }
1555         case TC_NS_CLIENT_IOCTL_LATEINIT: {
1556             ret = TcNsLateInit(arg);
1557             break;
1558         }
1559         default:
1560             tloge("invalid cmd!\n");
1561             return ret;
1562     }
1563     tlogd("TC_NS_ClientIoctl ret = 0x%x\n", ret);
1564     return ret;
1565 }
1566 
TcClientIoctlOthers(struct file * file,int cmd,unsigned long arg)1567 static int TcClientIoctlOthers(struct file *file, int cmd, unsigned long arg)
1568 {
1569     void *argp = (void __user *)(uintptr_t)arg;
1570     int ret = TEEC_ERROR_GENERIC;
1571 
1572     switch (cmd) {
1573         /* IOCTLs for the secure storage daemon */
1574         case TC_NS_CLIENT_IOCTL_WAIT_EVENT:
1575         case TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE:
1576         case TC_NS_CLIENT_IOCTL_REGISTER_AGENT:
1577         case TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT:
1578         case TC_NS_CLIENT_IOCTL_SYC_SYS_TIME:
1579         case TC_NS_CLIENT_IOCTL_LOAD_TTF_FILE_AND_NOTCH_HEIGHT:
1580         case TC_NS_CLIENT_IOCTL_SET_NATIVECA_IDENTITY:
1581         case TC_NS_CLIENT_IOCTL_LATEINIT:
1582             ret = TcAgentIoctl(file, cmd, arg);
1583             break;
1584 #ifdef DEF_ENG
1585         case TC_NS_CLIENT_IOCTL_TST_CMD_REQ: {
1586             tlogd("come into tst cmd\n");
1587             ret = TcNsTstCmd(file->f_priv, argp);
1588             break;
1589         }
1590 #endif
1591         case TC_NS_CLIENT_IOCTL_GET_TEE_VERSION: {
1592             ret = TcNsGetTeeVersion(file->f_priv, argp);
1593             break;
1594         }
1595         case TC_NS_CLIENT_IOCTL_UNMAP_SHARED_MEM: {
1596             ret = TcNsSharedMemUnmap(file->f_priv, (unsigned int)(UINTPTR)argp);
1597             break;
1598         }
1599         default: {
1600             tloge("invalid cmd 0x%x!\n", cmd);
1601             break;
1602         }
1603     }
1604     return ret;
1605 }
1606 
TcClientIoctl(struct file * file,int cmd,unsigned long arg)1607 static int TcClientIoctl(struct file *file, int cmd, unsigned long arg)
1608 {
1609     int ret = TEEC_ERROR_GENERIC;
1610     void *argp = (void __user *)(uintptr_t)arg;
1611     TcNsDevFile *devFile = file->f_priv;
1612     TcNsClientContext clientContext = {{0}};
1613 
1614     switch (cmd) {
1615         /* IOCTLs for the CAs */
1616         case TC_NS_CLIENT_IOCTL_SES_OPEN_REQ:
1617             /* Upvote for peripheral zone votage, needed by Coresight.
1618              * Downvote will be processed inside CFC_RETURN_PMCLK_ON_COND
1619              */
1620         /* Fall through */
1621         case TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ:
1622         case TC_NS_CLIENT_IOCTL_SEND_CMD_REQ:
1623             ret = TcClientSessionIoctl(file, cmd, arg);
1624             break;
1625         case TC_NS_CLIENT_IOCTL_LOAD_APP_REQ:
1626             ret = TcNsLoadSecfile(devFile, argp);
1627             break;
1628         case TC_NS_CLIENT_IOCTL_CANCEL_CMD_REQ:
1629             if (argp == NULL) {
1630                 tloge("argp is NULL input buffer\n");
1631                 ret = -EINVAL;
1632                 break;
1633             }
1634             if (copy_from_user(&clientContext, argp,
1635                 sizeof(clientContext))) {
1636                 tloge("copy from user failed\n");
1637                 ret = -ENOMEM;
1638                 break;
1639             }
1640             ret = TcNsSendCmd(devFile, &clientContext);
1641             break;
1642         /* This is the login information
1643          * and is set teecd when client opens a new session
1644          */
1645         case TC_NS_CLIENT_IOCTL_LOGIN: {
1646             ret = TcNsClientLoginFunc(devFile, argp);
1647             break;
1648         }
1649         default:
1650             ret = TcClientIoctlOthers(file, cmd, arg);
1651             break;
1652     }
1653 
1654     tlogd("tc client ioctl ret = 0x%x\n", ret);
1655     return ret;
1656 }
1657 
TcClientOpen(struct file * file)1658 static int TcClientOpen(struct file *file)
1659 {
1660     int ret;
1661     TcNsDevFile *dev = NULL;
1662     ret = CheckProcessAccess(OsCurrTaskGet());
1663     if (ret) {
1664         tloge(KERN_ERR "teecd service may be exploited 0x%x\n", ret);
1665         return -EPERM;
1666     }
1667 
1668     file->f_priv = NULL;
1669     ret = TcNsClientOpen(&dev, TEE_REQ_FROM_USER_MODE);
1670     if (ret == TEEC_SUCCESS) {
1671         file->f_priv = dev;
1672     }
1673     return ret;
1674 }
1675 
TcClientClose(struct file * file)1676 static int TcClientClose(struct file *file)
1677 {
1678     int ret = TEEC_ERROR_GENERIC;
1679     TcNsDevFile *dev = file->f_priv;
1680     bool checkValue = false;
1681 
1682     checkValue = (IsTeecdProcess(g_teecdTask, OsCurrTaskGet())) &&
1683         (!TcNsGetUid());
1684     if (checkValue == true) {
1685         /* for teecd close fd */
1686         checkValue = (g_teecdTask->taskStatus & OS_TASK_STATUS_EXIT) ||
1687             (OsCurrTaskGet()->taskStatus & OS_TASK_STATUS_EXIT);
1688         if (checkValue == true) {
1689             /* when teecd is be killed or crash */
1690             tloge("teecd is killed, something bad must be happened!!!\n");
1691             if (IsSystemAgent(dev)) {
1692                 /* for teecd agent close fd */
1693                 SendEventResponseSingle(dev);
1694                 FreeDev(dev);
1695             } else {
1696                 /* for ca damon close fd */
1697                 ret = NsClientCloseTeecdNotAgent(dev);
1698             }
1699         } else {
1700             /* for ca damon close fd when ca damon close fd
1701              *  later than HAL thread
1702              */
1703             ret = TcNsClientClose(dev);
1704         }
1705     } else {
1706         /* for CA(HAL thread) close fd */
1707         ret = TcNsClientClose(dev);
1708     }
1709     file->f_priv = NULL;
1710     return ret;
1711 }
1712 
1713 static const struct file_operations_vfs g_tcNsClientFops = {
1714     .open = TcClientOpen,
1715     .close = TcClientClose,
1716     .ioctl = TcClientIoctl,
1717     .mmap = TcClientMmap,
1718 };
1719 
ScheduleWorkOn(int cpu,struct work_struct * work)1720 bool ScheduleWorkOn(int cpu, struct work_struct *work)
1721 {
1722     return queue_work(g_tzdriverWq, work);
1723 }
1724 
TcNsClientInit(void)1725 static int TcNsClientInit(void)
1726 {
1727     int ret;
1728 
1729     tlogd("TcNsClientInit\n");
1730 
1731     ret = CreateTcClientDevice(TC_NS_CLIENT_DEV_NAME, &g_tcNsClientFops);
1732     if (ret != EOK) {
1733         tloge("create tee device error.\n");
1734         return ret;
1735     }
1736     ret = memset_s(&g_tcNsDevList, sizeof(g_tcNsDevList), 0,
1737         sizeof(g_tcNsDevList));
1738     if (ret != EOK) {
1739         return ret;
1740     }
1741 
1742     INIT_LIST_HEAD(&g_tcNsDevList.devFileList);
1743     mutex_init(&g_tcNsDevList.devLock);
1744     INIT_LIST_HEAD(&g_serviceList);
1745 
1746     g_tzdriverWq = create_workqueue("g_tzdriverWq");
1747     if (g_tzdriverWq == NULL) {
1748         tloge("couldn't create workqueue.\n");
1749         return -ENOMEM;
1750     }
1751     return 0;
1752 }
1753 
TcTeeosInit(void)1754 static int TcTeeosInit(void)
1755 {
1756     int ret;
1757 
1758     ret = SmcInitData();
1759     if (ret < 0) {
1760         tloge("smc init failed\n");
1761         return ret;
1762     }
1763 
1764     ret = TcMemInit();
1765     if (ret < 0) {
1766         tloge("tcmem init failed\n");
1767         goto SMC_DATA_FREE;
1768     }
1769 
1770     // following failure don't block tzdriver init proc;
1771     AgentInit();
1772 
1773     ret = TzSpiInit();
1774     if (ret) {
1775         tloge("tz spi init failed\n");
1776     }
1777     return 0;
1778 
1779 SMC_DATA_FREE:
1780     SmcFreeData();
1781     return ret;
1782 }
1783 
TcReInit(void)1784 static void TcReInit(void)
1785 {
1786     int ret = 0;
1787 
1788     if (InitSmcSvcThread()) {
1789         tloge("init svc thread\n");
1790         ret = -EFAULT;
1791     }
1792 
1793     if (ret) {
1794         tloge("Caution! Running environment init failed!\n");
1795     }
1796 }
1797 
TcInit(void)1798 int TcInit(void)
1799 {
1800     int ret = TcNsClientInit();
1801     if (ret != 0) {
1802         goto TC_INIT_FAIL;
1803     }
1804 
1805     ret = TcTeeosInit();
1806     if (ret != 0) {
1807         goto TC_INIT_FAIL;
1808     }
1809     // run-time environment init failure don't block tzdriver init proc;
1810     TcReInit();
1811 
1812 #ifdef DEF_ENG
1813     TzdebugInit();
1814 #endif
1815     return 0;
1816 
1817 TC_INIT_FAIL:
1818     ret = unregister_driver(TC_NS_CLIENT_DEV_NAME);
1819     if (g_tzdriverWq != NULL) {
1820         destroy_workqueue(g_tzdriverWq);
1821     }
1822     return ret;
1823 }
1824