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 
13 #include "cadaemon_service.h"
14 #include <cerrno>
15 #include <csignal>
16 #include <memory>
17 #include <thread>
18 #include <pthread.h>
19 #include <securec.h>
20 #include <sys/syscall.h>
21 #include <dlfcn.h>
22 #include <sys/tgkill.h>
23 #include <sys/types.h>
24 #include "if_system_ability_manager.h"
25 #include "ipc_skeleton.h"
26 #include "ipc_types.h"
27 #include "iservice_registry.h"
28 #include "string_ex.h"
29 #include "system_ability_definition.h"
30 #include "tee_log.h"
31 #include "tee_auth_system.h"
32 #include "tcu_authentication.h"
33 #include "tc_ns_client.h"
34 #include "tee_ioctl_cmd.h"
35 #include <sys/ioctl.h>
36 
37 using namespace std;
38 namespace OHOS {
39 namespace CaDaemon {
40 static LIST_DECLARE(g_teecProcDataList);
41 static LIST_DECLARE(g_teecTidList);
42 static pthread_mutex_t g_mutexTidList = PTHREAD_MUTEX_INITIALIZER;
43 
44 REGISTER_SYSTEM_ABILITY_BY_ID(CaDaemonService, CA_DAEMON_ID, true);
45 
OnStart()46 void CaDaemonService::OnStart()
47 {
48     if (state_ == ServiceRunningState::STATE_RUNNING) {
49         tlogd("CaDaemonService has already started.");
50         return;
51     }
52     if (!Init()) {
53         tloge("failed to init CaDaemonService");
54         return;
55     }
56     state_ = ServiceRunningState::STATE_RUNNING;
57     if (GetTEEVersion()) {
58         tloge("get the tee version failed\n");
59         mTeeVersion = 0;
60     }
61     tloge("the tee version is %x\n", mTeeVersion);
62     CreateTuiThread();
63 }
64 
GetTEEVersion()65 int CaDaemonService::GetTEEVersion()
66 {
67     int ret;
68 
69     int fd = open(TC_PRIVATE_DEV_NAME, O_RDWR);
70     if (fd == -1) {
71         tloge("Failed to open %s: %d\n", TC_PRIVATE_DEV_NAME, errno);
72         return -1;
73     }
74 
75     ret = ioctl(fd, TC_NS_CLIENT_IOCTL_GET_TEE_VERSION, &mTeeVersion);
76     close(fd);
77     if (ret != 0) {
78         tloge("Failed to get tee version, err=%d\n", ret);
79         return -1;
80     }
81 
82     return ret;
83 }
84 
CreateTuiThread()85 void CaDaemonService::CreateTuiThread()
86 {
87 #if defined(__LP64__)
88     void *handle = dlopen("/system/lib64/libcadaemon_tui.so", RTLD_LAZY);
89 #else
90     void *handle = dlopen("/system/lib/libcadaemon_tui.so", RTLD_LAZY);
91 #endif
92     if (handle == nullptr) {
93         tlogi("tui daemon handle is null");
94         return;
95     }
96 
97     void (*teeTuiThreadFunc)(void) = nullptr;
98     teeTuiThreadFunc = (void(*)(void))dlsym(handle, "TeeTuiThreadWork");
99     if (teeTuiThreadFunc == nullptr) {
100         tloge("teeTuiThreadFunc is null\n");
101         return;
102     }
103     std::thread tuiThread(teeTuiThreadFunc);
104     tuiThread.detach();
105     tlogi("CaDaemonService teeTuiThreadWork start \n");
106 }
107 
Init()108 bool CaDaemonService::Init()
109 {
110     tlogi("CaDaemonService::Init ready to init");
111     if (!registerToService_) {
112         bool ret = Publish(this);
113         if (!ret) {
114             tloge("CaDaemonService::Init Publish failed!");
115             return false;
116         }
117         registerToService_ = true;
118     }
119     tlogi("CaDaemonService::Init init success");
120     return true;
121 }
122 
OnStop()123 void CaDaemonService::OnStop()
124 {
125     tlogi("CaDaemonService service stop");
126     state_ = ServiceRunningState::STATE_NOT_START;
127     registerToService_ = false;
128 }
129 
GetProcdataByPid(int pid)130 static DaemonProcdata *GetProcdataByPid(int pid)
131 {
132     /* found server procdata */
133     DaemonProcdata *procDataInList = nullptr;
134     struct ListNode *ptr = nullptr;
135 
136     /* Paramters right, start execution */
137     if (!LIST_EMPTY(&g_teecProcDataList)) {
138         LIST_FOR_EACH(ptr, &g_teecProcDataList) {
139             DaemonProcdata *tmp = LIST_ENTRY(ptr, DaemonProcdata, procdataHead);
140             if (tmp->callingPid == pid) {
141                 procDataInList = tmp;
142                 break;
143             }
144         }
145     }
146     return procDataInList;
147 }
148 
CheckProcDataFdFull(DaemonProcdata * procData)149 static bool CheckProcDataFdFull(DaemonProcdata *procData)
150 {
151     int i;
152     DaemonProcdata *tmpProcData = procData;
153     for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
154         if (tmpProcData->cxtFd[i] == -1) {
155             return false;
156         }
157     }
158     return true;
159 }
160 
CheckProcDataFdEmpty(DaemonProcdata * procData)161 static bool CheckProcDataFdEmpty(DaemonProcdata *procData)
162 {
163     int i;
164     for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
165         if (procData->cxtFd[i] != -1) {
166             return false;
167         }
168     }
169     return true;
170 }
171 
RemoveContextFromProcData(DaemonProcdata * outProcData,int32_t outContextFd)172 static void RemoveContextFromProcData(DaemonProcdata *outProcData, int32_t outContextFd)
173 {
174     int i;
175     for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
176         if (outContextFd == outProcData->cxtFd[i]) {
177             outProcData->cxtFd[i] = -1;
178             return;
179         }
180     }
181     tloge("can not find context in outProcdata\n");
182 }
183 
TidMutexLock(void)184 static int32_t TidMutexLock(void)
185 {
186     int lockRet = pthread_mutex_lock(&g_mutexTidList);
187     return lockRet;
188 }
189 
TidMutexUnlock(int lockRet)190 static void TidMutexUnlock(int lockRet)
191 {
192     int unlockRet;
193     if (lockRet != 0) {
194         tloge("not exe, mutex not in lock state. lock_ret = %{public}d\n", lockRet);
195         return;
196     }
197     unlockRet = pthread_mutex_unlock(&g_mutexTidList);
198     if (unlockRet != 0) {
199         tloge("exe mutexUnlock error, ret = %{public}d\n", unlockRet);
200     }
201 }
202 
SigUsr1Handler(int sign)203 static void SigUsr1Handler(int sign)
204 {
205     (void)sign;
206     return;
207 }
208 
RemoveTidFromList(TidData * tidData)209 static void RemoveTidFromList(TidData *tidData)
210 {
211     int retMutexLock = TidMutexLock();
212     if (retMutexLock) {
213         tloge("tid mutex lock failed\n");
214     }
215 
216     ListRemoveEntry(&tidData->tidHead);
217     TidMutexUnlock(retMutexLock);
218     free(tidData);
219     return;
220 }
221 
AddTidData(TidData ** tidData,int pid)222 static TEEC_Result AddTidData(TidData **tidData, int pid)
223 {
224     int mutexRet;
225     *tidData = static_cast<TidData *>(malloc(sizeof(TidData)));
226     if (*tidData == nullptr) {
227         tloge("tid_data malloc failed\n");
228         return TEEC_FAIL;
229     }
230     (*tidData)->tid = syscall(SYS_gettid);
231     (*tidData)->callingPid = pid;
232     ListInit(&(*tidData)->tidHead);
233 
234     mutexRet = TidMutexLock();
235     if (mutexRet != 0) {
236         tloge("tid mutex lock failed\n");
237         free(*tidData);
238         *tidData = nullptr;
239         return TEEC_FAIL;
240     }
241     ListInsertTail(&g_teecTidList, &(*tidData)->tidHead);
242     TidMutexUnlock(mutexRet);
243     tlogd("tid %{public}d is sending command to TEE\n", (*tidData)->tid);
244     return TEEC_SUCCESS;
245 }
246 
SendSigToTzdriver(int pid)247 static void SendSigToTzdriver(int pid)
248 {
249     int mutexRet;
250     struct ListNode *ptr = nullptr;
251 
252     signal(SIGUSR1, SigUsr1Handler);
253     tlogd("ignore signal SIGUSR1!\n");
254 
255     mutexRet = TidMutexLock();
256     if (mutexRet != 0) {
257         tloge("tid mutex lock failed\n");
258         return;
259     }
260     if (!LIST_EMPTY(&g_teecTidList)) {
261         LIST_FOR_EACH(ptr, &g_teecTidList) {
262             TidData *tmp = LIST_ENTRY(ptr, TidData, tidHead);
263             if (tmp->callingPid == pid) {
264                 int ret = tgkill(getpid(), tmp->tid, SIGUSR1);
265                 tlogd("send signal SIGUSR1 to tid: %{public}d! ret = %{public}d\n", tmp->tid, ret);
266             }
267         }
268     }
269     TidMutexUnlock(mutexRet);
270 }
271 
IsValidContextWithoutLock(const TEEC_Context * context,int pid)272 bool CaDaemonService::IsValidContextWithoutLock(const TEEC_Context *context, int pid)
273 {
274     int i;
275     DaemonProcdata *outProcData = GetProcdataByPid(pid);
276 
277     bool tmpCheckStatus = (outProcData == nullptr || context == nullptr);
278     if (tmpCheckStatus) {
279         return false;
280     }
281 
282     if (context->fd < 0) {
283         return false;
284     }
285 
286     for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
287         if (context->fd == outProcData->cxtFd[i]) {
288             return true;
289         }
290     }
291     return false;
292 }
293 
IsValidContext(const TEEC_Context * context,int pid)294 bool CaDaemonService::IsValidContext(const TEEC_Context *context, int pid)
295 {
296     lock_guard<mutex> autoLock(mProcDataLock);
297     return IsValidContextWithoutLock(context, pid);
298 }
299 
CallGetProcDataPtr(int pid)300 DaemonProcdata *CaDaemonService::CallGetProcDataPtr(int pid)
301 {
302     DaemonProcdata *outProcData = GetProcdataByPid(pid);
303     if (outProcData != nullptr) {
304         if (CheckProcDataFdFull(outProcData)) {
305             tloge("pid[%{public}d] can not get more context, please finalize some of them\n", pid);
306             return nullptr;
307         }
308     } else {
309         auto *procData = static_cast<DaemonProcdata *>(malloc(sizeof(DaemonProcdata)));
310         if (procData == nullptr) {
311             tloge("procdata malloc failed\n");
312             return nullptr;
313         }
314         (void)memset_s(procData, sizeof(DaemonProcdata), 0, sizeof(DaemonProcdata));
315 
316         for (int i = 0; i < MAX_CXTCNT_ONECA; i++) {
317             procData->cxtFd[i] = -1;
318         }
319         procData->callingPid = pid;
320         ListInit(&(procData->procdataHead));
321         ListInsertTail(&g_teecProcDataList, &procData->procdataHead);
322 
323         outProcData = procData;
324     }
325     return outProcData;
326 }
327 
SetContextToProcData(int32_t pid,TEEC_ContextInner * outContext)328 TEEC_Result CaDaemonService::SetContextToProcData(int32_t pid, TEEC_ContextInner *outContext)
329 {
330     int i;
331     {
332         lock_guard<mutex> autoLock(mProcDataLock);
333         DaemonProcdata *outProcData = CallGetProcDataPtr(pid);
334         if (outProcData == nullptr) {
335             tloge("proc data not found\n");
336             return TEEC_FAIL;
337         }
338 
339         for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
340             if (outProcData->cxtFd[i] == -1) {
341                 outProcData->cxtFd[i] = outContext->fd;
342                 return TEEC_SUCCESS;
343             }
344         }
345     }
346 
347     tloge("the cnt of contexts in outProcData is already %{public}d, please finalize some of them\n", i);
348     return TEEC_FAIL;
349 }
350 
PutBnContextAndReleaseFd(int32_t pid,TEEC_ContextInner * outContext)351 void CaDaemonService::PutBnContextAndReleaseFd(int32_t pid, TEEC_ContextInner *outContext)
352 {
353     if (outContext == nullptr) {
354         tlogd("put context is null\n");
355         return;
356     }
357 
358     int32_t contextFd = outContext->fd;
359     DaemonProcdata *outProcData = nullptr;
360 
361     lock_guard<mutex> autoLock(mProcDataLock);
362 
363     if (!PutBnContext(outContext)) {
364         return;
365     }
366 
367     tloge("clear context success\n");
368 
369     outProcData = GetProcdataByPid(pid);
370     if (outProcData == nullptr) {
371         tloge("outProcdata is nullptr\n");
372         return;
373     }
374 
375     RemoveContextFromProcData(outProcData, contextFd);
376 
377     if (CheckProcDataFdEmpty(outProcData)) {
378         tloge("ProcData is empty\n");
379         ListRemoveEntry(&outProcData->procdataHead);
380         free(outProcData);
381     } else {
382         tlogd("still have context not finalize in pid[%{public}d]\n", pid);
383     }
384 }
385 
InitCaAuthInfo(CaAuthInfo * caInfo)386 static TEEC_Result InitCaAuthInfo(CaAuthInfo *caInfo)
387 {
388     static bool sendXmlSuccFlag = false;
389     /* Trans the system xml file to tzdriver */
390     if (!sendXmlSuccFlag) {
391         tlogd("cadaemon send system hash xml file\n");
392         if (TcuAuthentication(HASH_TYPE_SYSTEM) != 0) {
393             tloge("send system hash xml file failed\n");
394         } else {
395             sendXmlSuccFlag = true;
396         }
397     }
398 
399     uint32_t callingTokenID = IPCSkeleton::GetCallingTokenID();
400     TEEC_Result ret = (TEEC_Result)ConstructCaAuthInfo(callingTokenID, caInfo);
401     if (ret != 0) {
402         tloge("construct ca auth info failed, ret %d\n", ret);
403         return TEEC_FAIL;
404     }
405 
406     return TEEC_SUCCESS;
407 }
408 
ReleaseContext(int32_t pid,TEEC_ContextInner ** contextInner)409 void CaDaemonService::ReleaseContext(int32_t pid, TEEC_ContextInner **contextInner)
410 {
411     TEEC_Context tempContext = { 0 };
412     PutBnContextAndReleaseFd(pid, *contextInner); /* pair with ops_cnt++ when add to list */
413     tempContext.fd = (*contextInner)->fd;
414     if (CallFinalizeContext(pid, &tempContext) < 0) {
415         tloge("CallFinalizeContext failed!\n");
416     }
417 
418     /* contextInner have been freed by finalize context */
419     *contextInner = nullptr;
420 }
421 
InitializeContext(const char * name,MessageParcel & reply)422 TEEC_Result CaDaemonService::InitializeContext(const char *name, MessageParcel &reply)
423 {
424     bool writeRet = false;
425     TEEC_Result ret = TEEC_FAIL;
426     TEEC_ContextInner *contextInner = (TEEC_ContextInner *)malloc(sizeof(*contextInner));
427     CaAuthInfo *caInfo = (CaAuthInfo *)malloc(sizeof(*caInfo));
428     if (contextInner == nullptr || caInfo == nullptr) {
429         tloge("malloc context and cainfo failed\n");
430         goto FREE_CONTEXT;
431     }
432     (void)memset_s(contextInner, sizeof(*contextInner), 0, sizeof(*contextInner));
433     (void)memset_s(caInfo, sizeof(*caInfo), 0, sizeof(*caInfo));
434     caInfo->pid = IPCSkeleton::GetCallingPid();
435     caInfo->uid = (unsigned int)IPCSkeleton::GetCallingUid();
436 
437     if (InitCaAuthInfo(caInfo) != TEEC_SUCCESS) {
438         goto FREE_CONTEXT;
439     }
440 
441     ret = TEEC_InitializeContextInner(contextInner, caInfo);
442     if (ret != TEEC_SUCCESS) {
443         goto FREE_CONTEXT;
444     }
445 
446     contextInner->callFromService = true;
447     ret = SetContextToProcData(caInfo->pid, contextInner);
448     if (ret != TEEC_SUCCESS) {
449         goto RELEASE_CONTEXT;
450     }
451 
452     writeRet = reply.WriteInt32((int32_t)ret);
453     if (!writeRet) {
454         ret = TEEC_FAIL;
455         goto RELEASE_CONTEXT;
456     }
457     writeRet = reply.WriteInt32(contextInner->fd);
458     if (!writeRet) {
459         ret = TEEC_FAIL;
460         goto RELEASE_CONTEXT;
461     }
462 
463     PutBnContextAndReleaseFd(caInfo->pid, contextInner); /* pair with ops_cnt++ when add to list */
464     goto END;
465 
466 RELEASE_CONTEXT:
467     ReleaseContext(caInfo->pid, &contextInner);
468 
469 FREE_CONTEXT:
470     if (contextInner != nullptr) {
471         free(contextInner);
472     }
473 
474 END:
475     if (caInfo != nullptr) {
476         (void)memset_s(caInfo, sizeof(*caInfo), 0, sizeof(*caInfo));
477         free(caInfo);
478     }
479     return ret;
480 }
481 
FinalizeContext(TEEC_Context * context)482 TEEC_Result CaDaemonService::FinalizeContext(TEEC_Context *context)
483 {
484     pid_t pid = IPCSkeleton::GetCallingPid();
485     if (context == nullptr) {
486         tloge("finalizeContext: invalid context!\n");
487         return TEEC_FAIL;
488     }
489 
490     if (!IsValidContext(context, pid)) {
491         tloge("context and procdata have been released by service_died!\n");
492         return TEEC_FAIL;
493     }
494 
495     return CallFinalizeContext(pid, context);
496 }
497 
CallFinalizeContext(int32_t pid,const TEEC_Context * contextPtr)498 TEEC_Result CaDaemonService::CallFinalizeContext(int32_t pid, const TEEC_Context *contextPtr)
499 {
500     TEEC_ContextInner *outContext = FindAndRemoveBnContext(contextPtr);
501     if (outContext == nullptr) {
502         tloge("no context found in service!\n");
503         return TEEC_FAIL;
504     }
505 
506     PutBnContextAndReleaseFd(pid, outContext); /* pair with initialize context */
507 
508     return TEEC_SUCCESS;
509 }
510 
511 
CallGetBnContext(const TEEC_Context * inContext,int pid,TEEC_Session ** outSession,TEEC_ContextInner ** outContext)512 TEEC_Result CaDaemonService::CallGetBnContext(const TEEC_Context *inContext,
513     int pid, TEEC_Session **outSession, TEEC_ContextInner **outContext)
514 {
515     TEEC_ContextInner *tempContext = nullptr;
516 
517     if (inContext == nullptr) {
518         tloge("getBnContext: invalid context!\n");
519         return TEEC_FAIL;
520     }
521 
522     tempContext = GetBnContext(inContext);
523     if (tempContext == nullptr) {
524         tloge("no context found in auth_daemon service.\n");
525         return TEEC_ERROR_BAD_PARAMETERS;
526     }
527 
528     TEEC_Session *tempSession = (TEEC_Session *)malloc(sizeof(TEEC_Session));
529     if (tempSession == nullptr) {
530         tloge("tempSession malloc failed!\n");
531         PutBnContextAndReleaseFd(pid, tempContext);
532         return TEEC_FAIL;
533     }
534     (void)memset_s(tempSession, sizeof(TEEC_Session), 0x00, sizeof(TEEC_Session));
535 
536     *outSession = tempSession;
537     *outContext = tempContext;
538     return TEEC_SUCCESS;
539 }
540 
WriteSession(MessageParcel & reply,TEEC_Session * session)541 static bool WriteSession(MessageParcel &reply, TEEC_Session *session)
542 {
543     if (session == nullptr) {
544         return reply.WriteBool(false);
545     }
546 
547     bool parRet = reply.WriteBool(true);
548     CHECK_ERR_RETURN(parRet, true, false);
549 
550     TEEC_Session retSession;
551     (void)memcpy_s(&retSession, sizeof(TEEC_Session), session, sizeof(TEEC_Session));
552 
553     /* clear session ptr, avoid to write back to CA */
554     retSession.context = nullptr;
555     (void)memset_s(&(retSession.head), sizeof(struct ListNode), 0, sizeof(struct ListNode));
556     return reply.WriteBuffer(&retSession, sizeof(retSession));
557 }
558 
WriteOperation(MessageParcel & reply,TEEC_Operation * operation)559 static bool WriteOperation(MessageParcel &reply, TEEC_Operation *operation)
560 {
561     if (operation == nullptr) {
562         return reply.WriteBool(false);
563     }
564 
565     bool parRet = reply.WriteBool(true);
566     CHECK_ERR_RETURN(parRet, true, false);
567 
568     TEEC_Operation retOperation;
569     (void)memcpy_s(&retOperation, sizeof(TEEC_Operation), operation, sizeof(TEEC_Operation));
570 
571     /* clear operation ptr avoid writing back to CA */
572     retOperation.session = nullptr;
573     for (uint32_t i = 0; i < TEEC_PARAM_NUM; i++) {
574         uint32_t type = TEEC_PARAM_TYPE_GET(retOperation.paramTypes, i);
575         switch (type) {
576             case TEEC_MEMREF_TEMP_INPUT:
577             case TEEC_MEMREF_TEMP_OUTPUT:
578             case TEEC_MEMREF_TEMP_INOUT:
579                 retOperation.params[i].tmpref.buffer = nullptr;
580                 break;
581             case TEEC_MEMREF_WHOLE:
582             case TEEC_MEMREF_PARTIAL_INPUT:
583             case TEEC_MEMREF_PARTIAL_OUTPUT:
584             case TEEC_MEMREF_PARTIAL_INOUT:
585                 retOperation.params[i].memref.parent = nullptr;
586                 break;
587             default:
588                 break;
589         }
590     }
591 
592     return reply.WriteBuffer(&retOperation, sizeof(retOperation));
593 }
594 
WriteSharedMem(MessageParcel & data,TEEC_SharedMemory * shm)595 static bool WriteSharedMem(MessageParcel &data, TEEC_SharedMemory *shm)
596 {
597     TEEC_SharedMemory retShm;
598     (void)memcpy_s(&retShm, sizeof(TEEC_SharedMemory),
599         shm, sizeof(TEEC_SharedMemory));
600 
601     /* clear retShm ptr, avoid writing back to CA */
602     retShm.buffer = nullptr;
603     retShm.context = nullptr;
604     memset_s(&(retShm.head), sizeof(struct ListNode), 0, sizeof(struct ListNode));
605     return data.WriteBuffer(&retShm, sizeof(retShm));
606 }
607 
CheckSizeStatus(uint32_t shmInfoOffset,uint32_t refSize,uint32_t totalSize,uint32_t memSize)608 static bool CheckSizeStatus(uint32_t shmInfoOffset, uint32_t refSize,
609                             uint32_t totalSize, uint32_t memSize)
610 {
611     return ((shmInfoOffset + refSize < shmInfoOffset) || (shmInfoOffset + refSize < refSize) ||
612             (shmInfoOffset + refSize > totalSize) || (refSize > memSize));
613 }
614 
CopyToShareMemory(TEEC_SharedMemory * shareMemBuf,uint8_t * data,uint32_t shmInfoOffset,uint32_t * shmOffset)615 static void CopyToShareMemory(TEEC_SharedMemory *shareMemBuf, uint8_t *data,
616                               uint32_t shmInfoOffset, uint32_t *shmOffset)
617 {
618     shareMemBuf->is_allocated = *reinterpret_cast<bool *>(data + shmInfoOffset);
619     shmInfoOffset += sizeof(bool);
620 
621     shareMemBuf->flags = *reinterpret_cast<uint32_t *>(data + shmInfoOffset);
622     shmInfoOffset += sizeof(uint32_t);
623 
624     shareMemBuf->ops_cnt = *reinterpret_cast<uint32_t *>(data + shmInfoOffset);
625     shmInfoOffset += sizeof(uint32_t);
626 
627     *shmOffset = *reinterpret_cast<uint32_t *>(data + shmInfoOffset);
628     shmInfoOffset += sizeof(uint32_t);
629 
630     shareMemBuf->size = *reinterpret_cast<uint32_t *>(data + shmInfoOffset);
631 }
632 
633 #define STRUCT_SIZE (4 * (sizeof(uint32_t)) + 1 * (sizeof(bool)))
TeecOptDecodePartialMem(DecodePara * paraDecode,uint8_t * data,InputPara * inputPara,TEEC_Operation * operation,uint32_t paramCnt)634 TEEC_Result CaDaemonService::TeecOptDecodePartialMem(DecodePara *paraDecode, uint8_t *data,
635     InputPara *inputPara, TEEC_Operation *operation, uint32_t paramCnt)
636 {
637     uint32_t shmInfoOffset = inputPara->offset;
638     uint32_t memSize = inputPara->memSize;
639     uint32_t shmOffset = 0;
640     uint32_t refSize = STRUCT_SIZE;
641     TEEC_SharedMemory *shareMemBuf = &(paraDecode->shm[paramCnt]);
642     TEEC_SharedMemoryInner **shmInner = &(paraDecode->shmInner[paramCnt]);
643     TEEC_ContextInner *outContext = paraDecode->contextInner;
644     TEEC_Parameter *params = &(operation->params[paramCnt]);
645 
646     if (CheckSizeStatus(shmInfoOffset, refSize, inputPara->totalSize, memSize)) {
647         goto FILLBUFFEREND;
648     }
649 
650     CopyToShareMemory(shareMemBuf, data, shmInfoOffset, &shmOffset);
651     memSize -= refSize;
652     shmInfoOffset += refSize;
653 
654     refSize = params->memref.size;
655     if (inputPara->paraType == TEEC_MEMREF_WHOLE)
656         refSize = shareMemBuf->size;
657 
658     if (CheckSizeStatus(shmInfoOffset, refSize, inputPara->totalSize, memSize)) {
659         goto FILLBUFFEREND;
660     }
661 
662     if (!shareMemBuf->is_allocated) {
663         shareMemBuf->buffer = data + shmInfoOffset;
664         params->memref.offset = 0;
665     } else {
666         TEEC_SharedMemoryInner *shmTemp = GetBnShmByOffset(shmOffset, outContext);
667         if (shmTemp == nullptr || shmTemp->buffer == nullptr) {
668             tloge("no shm buffer found in service!\n");
669             return TEEC_ERROR_BAD_PARAMETERS;
670         }
671         shareMemBuf->buffer = shmTemp->buffer;
672         *shmInner = shmTemp;
673     }
674     params->memref.parent = shareMemBuf;
675     memSize -= refSize;
676     shmInfoOffset += refSize;
677 
678     inputPara->offset = shmInfoOffset;
679     inputPara->memSize = memSize;
680     return TEEC_SUCCESS;
681 
682 FILLBUFFEREND:
683     tloge("partial mem:%{public}x greater than mem:%{public}x:%{public}x:%{public}x\n",
684         refSize, shmInfoOffset, memSize, inputPara->totalSize);
685     return TEEC_FAIL;
686 }
687 
GetTeecOptMem(TEEC_Operation * operation,size_t optMemSize,sptr<Ashmem> & optMem,DecodePara * paraDecode)688 TEEC_Result CaDaemonService::GetTeecOptMem(TEEC_Operation *operation, size_t optMemSize,
689     sptr<Ashmem> &optMem, DecodePara *paraDecode)
690 {
691     if (operation == nullptr || optMemSize == 0) {
692         return TEEC_SUCCESS;
693     }
694 
695     uint32_t paramType[TEEC_PARAM_NUM] = { 0 };
696     uint32_t paramCnt;
697     size_t sizeLeft    = optMemSize;
698     TEEC_Result teeRet = TEEC_SUCCESS;
699     uint32_t shmInfoOffset = 0;
700 
701     uint8_t *ptr = static_cast<uint8_t *>(const_cast<void *>(optMem->ReadFromAshmem(optMemSize, 0)));
702     if (ptr == nullptr) {
703         return TEEC_ERROR_BAD_PARAMETERS;
704     }
705 
706     for (paramCnt = 0; paramCnt < TEEC_PARAM_NUM; paramCnt++) {
707         paramType[paramCnt] = TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt);
708         if (IS_TEMP_MEM(paramType[paramCnt])) {
709             uint32_t refSize = operation->params[paramCnt].tmpref.size;
710             if (CheckSizeStatus(shmInfoOffset, refSize, optMemSize, sizeLeft)) {
711                 tloge("temp mem:%x greater than opt mem:%x:%x:%x\n",
712                     refSize, shmInfoOffset, (uint32_t)sizeLeft, (uint32_t)optMemSize);
713                 return TEEC_FAIL;
714             }
715             operation->params[paramCnt].tmpref.buffer = static_cast<void *>(ptr + shmInfoOffset);
716             sizeLeft -= refSize;
717             shmInfoOffset += refSize;
718         } else if (IS_PARTIAL_MEM(paramType[paramCnt])) {
719             InputPara tmpInputPara;
720             tmpInputPara.paraType = paramType[paramCnt];
721             tmpInputPara.offset = shmInfoOffset;
722             tmpInputPara.memSize = sizeLeft;
723             tmpInputPara.totalSize = optMemSize;
724             teeRet = TeecOptDecodePartialMem(paraDecode, ptr, &tmpInputPara, operation, paramCnt);
725             if (teeRet) {
726                 return teeRet;
727             }
728             shmInfoOffset = tmpInputPara.offset;
729             sizeLeft = tmpInputPara.memSize;
730         } else if (IS_VALUE_MEM(paramType[paramCnt])) {
731             /* no need to do some thing */
732             tlogd("value_mem, doing noting\n");
733         }
734 
735         if (teeRet != TEEC_SUCCESS) {
736             tloge("decodeTempMem: opt decode param fail. paramCnt: %{public}u, ret: 0x%{public}x\n",
737                 paramCnt, teeRet);
738             return teeRet;
739         }
740     }
741 
742     return TEEC_SUCCESS;
743 }
744 
RecOpenReply(uint32_t returnOrigin,TEEC_Result ret,TEEC_Session * outSession,TEEC_Operation * operation,MessageParcel & reply)745 static bool RecOpenReply(uint32_t returnOrigin, TEEC_Result ret, TEEC_Session *outSession,
746     TEEC_Operation *operation, MessageParcel &reply)
747 {
748     bool writeRet = reply.WriteUint32(returnOrigin);
749     CHECK_ERR_RETURN(writeRet, true, writeRet);
750 
751     writeRet = reply.WriteInt32((int32_t)ret);
752     CHECK_ERR_RETURN(writeRet, true, writeRet);
753 
754     if (ret != TEEC_SUCCESS) {
755         return false;
756     }
757 
758     writeRet = WriteSession(reply, outSession);
759     CHECK_ERR_RETURN(writeRet, true, writeRet);
760 
761     writeRet = WriteOperation(reply, operation);
762     CHECK_ERR_RETURN(writeRet, true, writeRet);
763 
764     return true;
765 }
766 
PrePareParmas(DecodePara & paraDecode,TaFileInfo & taFile,TEEC_ContextInner * outContext,const char * taPath,int32_t fd)767 static void PrePareParmas(DecodePara &paraDecode, TaFileInfo &taFile,
768     TEEC_ContextInner *outContext, const char *taPath, int32_t fd)
769 {
770     (void)memset_s(&(paraDecode.shm), sizeof(paraDecode.shm), 0x00, sizeof(paraDecode.shm));
771     (void)memset_s(&(paraDecode.shmInner), sizeof(paraDecode.shmInner), 0x00, sizeof(paraDecode.shmInner));
772     paraDecode.contextInner = outContext;
773 
774     taFile.taPath = (const uint8_t *)taPath;
775     if (fd >= 0) {
776         taFile.taFp = fdopen(fd, "r");
777     }
778 }
779 
CloseTaFile(TaFileInfo taFile)780 static void CloseTaFile(TaFileInfo taFile)
781 {
782     if (taFile.taFp != nullptr) {
783         fclose(taFile.taFp);
784         taFile.taFp = nullptr;
785     }
786 }
787 
OpenSession(TEEC_Context * context,const char * taPath,int32_t fd,const TEEC_UUID * destination,uint32_t connectionMethod,TEEC_Operation * operation,uint32_t optMemSize,sptr<Ashmem> & optMem,MessageParcel & reply)788 TEEC_Result CaDaemonService::OpenSession(TEEC_Context *context, const char *taPath, int32_t fd,
789     const TEEC_UUID *destination, uint32_t connectionMethod,
790     TEEC_Operation *operation, uint32_t optMemSize, sptr<Ashmem> &optMem, MessageParcel &reply)
791 {
792     TEEC_Result ret;
793     DecodePara paraDecode;
794     bool writeRet = false;
795     uint32_t returnOrigin = TEEC_ORIGIN_API;
796     TEEC_Session *outSession = nullptr;
797     TEEC_ContextInner *outContext = nullptr;
798     TidData *tidData = nullptr;
799     pid_t pid = IPCSkeleton::GetCallingPid();
800     TaFileInfo taFile = { .taPath = nullptr, .taFp = nullptr };
801 
802     ret = CallGetBnContext(context, pid, &outSession, &outContext);
803     if (ret != TEEC_SUCCESS) {
804         goto ERROR;
805     }
806 
807     PrePareParmas(paraDecode, taFile, outContext, taPath, fd);
808 
809     ret = GetTeecOptMem(operation, optMemSize, optMem, &paraDecode);
810     if (ret != TEEC_SUCCESS) {
811         goto ERROR;
812     }
813 
814     if (AddTidData(&tidData, pid) != TEEC_SUCCESS) {
815         ret = TEEC_FAIL;
816         goto ERROR;
817     }
818 
819     outSession->service_id = *destination;
820     outSession->session_id = 0;
821     ret = TEEC_OpenSessionInner(pid, &taFile, outContext, outSession,
822         destination, connectionMethod, nullptr, operation, &returnOrigin);
823     RemoveTidFromList(tidData);
824     tidData = nullptr;
825 
826     PutAllocShrMem(paraDecode.shmInner, TEEC_PARAM_NUM);
827     PutBnContextAndReleaseFd(pid, outContext); /* pairs with CallGetBnContext */
828 
829     writeRet = RecOpenReply(returnOrigin, ret, outSession, operation, reply);
830     if (!writeRet) {
831         goto ERROR;
832     }
833 
834     PutBnSession(outSession); /* pair with ops_cnt++ when add to list */
835     CloseTaFile(taFile);
836 
837     return TEEC_SUCCESS;
838 
839 ERROR:
840     writeRet = reply.WriteUint32(returnOrigin);
841     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
842 
843     writeRet = reply.WriteInt32((int32_t)ret);
844     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
845 
846     if (outSession != nullptr) {
847         free(outSession);
848         outSession = nullptr;
849     }
850 
851     CloseTaFile(taFile);
852 
853     return TEEC_SUCCESS;
854 }
855 
CallGetBnSession(int pid,const TEEC_Context * inContext,const TEEC_Session * inSession,TEEC_ContextInner ** outContext,TEEC_Session ** outSession)856 TEEC_Result CaDaemonService::CallGetBnSession(int pid, const TEEC_Context *inContext,
857     const TEEC_Session *inSession, TEEC_ContextInner **outContext, TEEC_Session **outSession)
858 {
859     TEEC_ContextInner *tmpContext = nullptr;
860     TEEC_Session *tmpSession = nullptr;
861 
862     bool tmpCheckStatus = ((inContext == nullptr) || (inSession == nullptr) ||
863                            (!IsValidContext(inContext, pid)));
864     if (tmpCheckStatus) {
865         tloge("getSession: invalid context!\n");
866         return TEEC_FAIL;
867     }
868 
869     tmpContext = GetBnContext(inContext);
870     if (tmpContext == nullptr) {
871         tloge("getSession: no context found in service!\n");
872         return TEEC_ERROR_BAD_PARAMETERS;
873     }
874 
875     tmpSession = GetBnSession(inSession, tmpContext);
876     if (tmpSession == nullptr) {
877         tloge("getSession: no session found in service!\n");
878         PutBnContextAndReleaseFd(pid, tmpContext);
879         return TEEC_ERROR_BAD_PARAMETERS;
880     }
881 
882     *outContext = tmpContext;
883     *outSession = tmpSession;
884     return TEEC_SUCCESS;
885 }
886 
InvokeCommand(TEEC_Context * context,TEEC_Session * session,uint32_t commandID,TEEC_Operation * operation,uint32_t optMemSize,sptr<Ashmem> & optMem,MessageParcel & reply)887 TEEC_Result CaDaemonService::InvokeCommand(TEEC_Context *context, TEEC_Session *session, uint32_t commandID,
888     TEEC_Operation *operation, uint32_t optMemSize, sptr<Ashmem> &optMem, MessageParcel &reply)
889 {
890     TEEC_ContextInner *outContext = nullptr;
891     TEEC_Session *outSession = nullptr;
892     TidData *tidData = nullptr;
893     TEEC_Result ret = TEEC_FAIL;
894     bool writeRet = false;
895     uint32_t returnOrigin = TEEC_ORIGIN_API;
896     DecodePara paraDecode;
897     pid_t pid = IPCSkeleton::GetCallingPid();
898 
899     ret = CallGetBnSession(pid, context, session, &outContext, &outSession);
900     if (ret != TEEC_SUCCESS) {
901         tloge("get context and session failed\n");
902         goto END;
903     }
904 
905     (void)memset_s(&(paraDecode.shm), sizeof(paraDecode.shm), 0x00, sizeof(paraDecode.shm));
906     (void)memset_s(&(paraDecode.shmInner), sizeof(paraDecode.shmInner), 0x00, sizeof(paraDecode.shmInner));
907     paraDecode.contextInner = outContext;
908     ret = GetTeecOptMem(operation, optMemSize, optMem, &paraDecode);
909     if (ret != TEEC_SUCCESS) {
910         PutBnSession(outSession);
911         PutBnContextAndReleaseFd(pid, outContext);
912         goto END;
913     }
914 
915     if (AddTidData(&tidData, pid) != TEEC_SUCCESS) {
916         goto END;
917     }
918     ret = TEEC_InvokeCommandInner(outContext, outSession, commandID, operation, &returnOrigin);
919     RemoveTidFromList(tidData);
920     tidData = nullptr;
921 
922     PutAllocShrMem(paraDecode.shmInner, TEEC_PARAM_NUM);
923     PutBnSession(outSession);
924     PutBnContextAndReleaseFd(pid, outContext);
925 
926 END:
927     writeRet = reply.WriteUint32(returnOrigin);
928     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
929 
930     writeRet = reply.WriteInt32((int32_t)ret);
931     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
932 
933     writeRet = WriteOperation(reply, operation);
934     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
935 
936     return TEEC_SUCCESS;
937 }
938 
CloseSession(TEEC_Session * session,TEEC_Context * context)939 TEEC_Result CaDaemonService::CloseSession(TEEC_Session *session, TEEC_Context *context)
940 {
941     pid_t pid = IPCSkeleton::GetCallingPid();
942     TidData *tidData = nullptr;
943     bool ret = (session == nullptr) || (context == nullptr) ||
944                (!IsValidContext(context, pid));
945     if (ret) {
946         tloge("closeSession: invalid context!\n");
947         return TEEC_FAIL;
948     }
949 
950     TEEC_ContextInner *outContext = GetBnContext(context);
951     if (outContext == nullptr) {
952         tloge("closeSession: no context found in service!\n");
953         return TEEC_FAIL;
954     }
955 
956     TEEC_Session *outSession = FindAndRemoveSession(session, outContext);
957     if (outSession == nullptr) {
958         tloge("closeSession: no session found in service!\n");
959         PutBnContextAndReleaseFd(pid, outContext);
960         return TEEC_FAIL;
961     }
962 
963     if (AddTidData(&tidData, pid) != TEEC_SUCCESS) {
964         return TEEC_FAIL;
965     }
966     TEEC_CloseSessionInner(outSession, outContext);
967     RemoveTidFromList(tidData);
968     tidData = nullptr;
969 
970     PutBnSession(outSession); /* pair with open session */
971     PutBnContextAndReleaseFd(pid, outContext);
972     return TEEC_SUCCESS;
973 }
974 
RegisterSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem,MessageParcel & reply)975 TEEC_Result CaDaemonService::RegisterSharedMemory(TEEC_Context *context,
976     TEEC_SharedMemory *sharedMem, MessageParcel &reply)
977 {
978     pid_t pid = IPCSkeleton::GetCallingPid();
979     TEEC_Result ret = TEEC_FAIL;
980     TEEC_SharedMemoryInner *outShm = nullptr;
981     TEEC_ContextInner *outContext = nullptr;
982     bool writeRet = false;
983 
984     if ((context == nullptr) || (sharedMem == nullptr)) {
985         tloge("registeMem: invalid context or sharedMem\n");
986         goto ERROR_END;
987     }
988 
989     outContext = GetBnContext(context);
990     if (outContext == nullptr) {
991         tloge("registeMem: no context found in service!\n");
992         ret = TEEC_ERROR_BAD_PARAMETERS;
993         goto ERROR_END;
994     }
995 
996     outShm = static_cast<TEEC_SharedMemoryInner *>(malloc(sizeof(TEEC_SharedMemoryInner)));
997     if (outShm == nullptr) {
998         tloge("registeMem: outShm malloc failed.\n");
999         goto ERROR_END;
1000     }
1001 
1002     (void)memset_s(outShm, sizeof(TEEC_SharedMemoryInner), 0, sizeof(TEEC_SharedMemoryInner));
1003 
1004     if (memcpy_s(outShm, sizeof(*outShm), sharedMem, sizeof(*sharedMem))) {
1005         tloge("registeMem: memcpy failed when copy data to shm, errno = %{public}d!\n", errno);
1006         free(outShm);
1007         goto ERROR_END;
1008     }
1009 
1010     ret = TEEC_RegisterSharedMemoryInner(outContext, outShm);
1011     if (ret != TEEC_SUCCESS) {
1012         free(outShm);
1013         PutBnContextAndReleaseFd(pid, outContext);
1014         goto ERROR_END;
1015     }
1016 
1017     PutBnShrMem(outShm);
1018     PutBnContextAndReleaseFd(pid, outContext);
1019 
1020     sharedMem->ops_cnt = outShm->ops_cnt;
1021     sharedMem->is_allocated = outShm->is_allocated;
1022 
1023     writeRet = reply.WriteInt32((int32_t)ret);
1024     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
1025 
1026     writeRet = WriteSharedMem(reply, sharedMem);
1027     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
1028 
1029     writeRet = reply.WriteUint32(outShm->offset);
1030     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
1031 
1032     return TEEC_SUCCESS;
1033 
1034 ERROR_END:
1035     writeRet = reply.WriteInt32((int32_t)ret);
1036     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
1037     return TEEC_SUCCESS;
1038 }
1039 
RecAllocReply(TEEC_Result ret,TEEC_SharedMemory * sharedMem,uint32_t offset,int32_t fd,MessageParcel & reply)1040 static bool RecAllocReply(TEEC_Result ret, TEEC_SharedMemory *sharedMem,
1041     uint32_t offset, int32_t fd, MessageParcel &reply)
1042 {
1043     bool writeRet = reply.WriteInt32((int32_t)ret);
1044     CHECK_ERR_RETURN(writeRet, true, writeRet);
1045 
1046     writeRet = WriteSharedMem(reply, sharedMem);
1047     CHECK_ERR_RETURN(writeRet, true, writeRet);
1048 
1049     writeRet = reply.WriteUint32(offset);
1050     CHECK_ERR_RETURN(writeRet, true, writeRet);
1051 
1052     writeRet = reply.WriteFileDescriptor(fd);
1053 
1054     return writeRet;
1055 }
1056 
AllocateSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem,MessageParcel & reply)1057 TEEC_Result CaDaemonService::AllocateSharedMemory(TEEC_Context *context,
1058     TEEC_SharedMemory *sharedMem, MessageParcel &reply)
1059 {
1060     TEEC_Result ret = TEEC_FAIL;
1061     bool writeRet = false;
1062     TEEC_ContextInner *outContext = nullptr;
1063     TEEC_SharedMemoryInner *outShm = nullptr;
1064     pid_t pid = IPCSkeleton::GetCallingPid();
1065 
1066     if ((context == nullptr) || (sharedMem == nullptr)) {
1067         tloge("allocateShamem: invalid context or sharedMem\n");
1068         goto ERROR;
1069     }
1070 
1071     outContext = GetBnContext(context);
1072     if (outContext == nullptr) {
1073         ret = TEEC_ERROR_BAD_PARAMETERS;
1074         goto ERROR;
1075     }
1076 
1077     outShm = (TEEC_SharedMemoryInner *)malloc(sizeof(TEEC_SharedMemoryInner));
1078     if (outShm == nullptr) {
1079         tloge("allocateShamem: outShm malloc failed\n");
1080         goto ERROR;
1081     }
1082 
1083     (void)memset_s(outShm, sizeof(*outShm), 0, sizeof(*outShm));
1084     (void)memcpy_s(outShm, sizeof(*outShm), sharedMem, sizeof(*sharedMem));
1085 
1086     ret = TEEC_AllocateSharedMemoryInner(outContext, outShm);
1087     if (ret != TEEC_SUCCESS) {
1088         goto ERROR;
1089     }
1090 
1091     sharedMem->ops_cnt = outShm->ops_cnt;
1092     sharedMem->is_allocated = outShm->is_allocated;
1093 
1094     writeRet = RecAllocReply(ret, sharedMem, outShm->offset, outContext->fd, reply);
1095     PutBnShrMem(outShm);
1096     PutBnContextAndReleaseFd(pid, outContext);
1097     if (!writeRet) {
1098         ListRemoveEntry(&outShm->head);
1099         PutBnShrMem(outShm);
1100         return TEEC_FAIL;
1101     }
1102 
1103     return TEEC_SUCCESS;
1104 
1105 ERROR:
1106     if (outShm != nullptr) {
1107         free(outShm);
1108     }
1109     PutBnContextAndReleaseFd(pid, outContext);
1110     writeRet = reply.WriteInt32((int32_t)ret);
1111     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
1112     return TEEC_SUCCESS;
1113 }
1114 
ReleaseSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem,uint32_t shmOffset,MessageParcel & reply)1115 TEEC_Result CaDaemonService::ReleaseSharedMemory(TEEC_Context *context,
1116     TEEC_SharedMemory *sharedMem, uint32_t shmOffset, MessageParcel &reply)
1117 {
1118     TEEC_ContextInner *outContext = nullptr;
1119     TEEC_SharedMemoryInner outShm;
1120     pid_t pid = IPCSkeleton::GetCallingPid();
1121 
1122     if ((context == nullptr) || (sharedMem == nullptr)) {
1123         tloge("releaseShamem: invalid context or sharedMem\n");
1124         return TEEC_ERROR_BAD_PARAMETERS;
1125     }
1126 
1127     outContext = GetBnContext(context);
1128     if (outContext == nullptr) {
1129         tloge("releaseShamem: no context found in service!\n");
1130         return TEEC_ERROR_BAD_PARAMETERS;
1131     }
1132 
1133     (void)memset_s(&outShm, sizeof(TEEC_SharedMemoryInner), 0, sizeof(TEEC_SharedMemoryInner));
1134 
1135     if (memcpy_s(&outShm, sizeof(outShm), sharedMem, sizeof(*sharedMem))) {
1136         tloge("releaseShamem: memcpy failed when copy data to shm, errno = %{public}d!\n", errno);
1137         return TEEC_FAIL;
1138     }
1139 
1140     outShm.offset = shmOffset;
1141     outShm.context = outContext;
1142 
1143     TEEC_ReleaseSharedMemoryInner(&outShm);
1144     PutBnContextAndReleaseFd(pid, outContext);
1145     return TEEC_SUCCESS;
1146 }
1147 
PutAllocShrMem(TEEC_SharedMemoryInner * shmInner[],uint32_t shmNum)1148 void CaDaemonService::PutAllocShrMem(TEEC_SharedMemoryInner *shmInner[], uint32_t shmNum)
1149 {
1150     uint32_t paramCnt;
1151     for (paramCnt = 0; paramCnt < shmNum; paramCnt++) {
1152         if (shmInner[paramCnt] != nullptr) {
1153             PutBnShrMem(shmInner[paramCnt]);
1154         }
1155     }
1156 
1157     return;
1158 }
1159 
SetCallBack(const sptr<IRemoteObject> & notify)1160 int32_t CaDaemonService::SetCallBack(const sptr<IRemoteObject> &notify)
1161 {
1162     if (notify == nullptr) {
1163         tloge("notify is nullptr\n");
1164         return ERR_UNKNOWN_OBJECT;
1165     }
1166 
1167     /* register CA dead notify */
1168     pid_t pid = IPCSkeleton::GetCallingPid();
1169     tloge("SetCallBack, ca pid=%{public}d", pid);
1170 
1171     int32_t ret = AddClient(pid, notify);
1172     if (ret != 0) {
1173         tloge("client link to death failed, pid=%{public}d", pid);
1174     }
1175     return ret;
1176 }
1177 
AddClient(pid_t pid,const sptr<IRemoteObject> & notify)1178 int32_t CaDaemonService::AddClient(pid_t pid, const sptr<IRemoteObject> &notify)
1179 {
1180     lock_guard<mutex> autoLock(mClientLock);
1181     size_t count = mClients.size();
1182     for (size_t index = 0; index < count; index++) {
1183         if (mClients[index]->GetMyPid() == pid) {
1184             tloge("client exist, pid=%{public}d", pid);
1185             return ERR_NONE;
1186         }
1187     }
1188 
1189     sptr<Client> c = new (std::nothrow) Client(pid, notify, this);
1190     if (c == nullptr) {
1191         tloge("addclient:new client failed, pid=%{public}d", pid);
1192         return ERR_UNKNOWN_REASON;
1193     }
1194     bool ret = notify->AddDeathRecipient(c);
1195     if (!ret) {
1196         tloge("addclient:link to death failed, pid=%{public}d", pid);
1197         return ERR_UNKNOWN_REASON;
1198     }
1199     mClients.push_back(c);
1200     return ERR_NONE;
1201 }
1202 
~Client()1203 CaDaemonService::Client::~Client()
1204 {
1205     tloge("delete client come in, pid=%{public}d", mPid);
1206 }
1207 
GetMyPid() const1208 pid_t CaDaemonService::Client::GetMyPid() const
1209 {
1210     return mPid;
1211 }
1212 
OnRemoteDied(const wptr<IRemoteObject> & deathNotify)1213 void CaDaemonService::Client::OnRemoteDied(const wptr<IRemoteObject> &deathNotify)
1214 {
1215     (void)deathNotify;
1216     tloge("teec client is died, pid=%{public}d", mPid);
1217     vector<sptr<Client>>::iterator vec;
1218     if (mService != nullptr) {
1219         size_t index = 0;
1220         lock_guard<mutex> autoLock(mService->mClientLock);
1221         for (vec = mService->mClients.begin(); vec != mService->mClients.end();) {
1222             if (mService->mClients[index]->GetMyPid() == mPid) {
1223                 tloge("died teec client found, pid=%{public}d", mPid);
1224                 /* release resources */
1225                 mService->ProcessCaDied(mPid);
1226                 vec = mService->mClients.erase(vec);
1227             } else {
1228                 ++vec;
1229                 index++;
1230             }
1231         }
1232     }
1233 }
1234 
CleanProcDataForOneCa(DaemonProcdata * procData)1235 void CaDaemonService::CleanProcDataForOneCa(DaemonProcdata *procData)
1236 {
1237     for (int i = 0; i < MAX_CXTCNT_ONECA; i++) {
1238         if (procData->cxtFd[i] == -1) {
1239             continue;
1240         }
1241 
1242         TEEC_Context context;
1243         context.fd = procData->cxtFd[i];
1244         procData->cxtFd[i] = -1;
1245 
1246         TEEC_ContextInner *outContext = FindAndRemoveBnContext(&context);
1247         if (outContext == nullptr) {
1248             tloge("no context found in service!\n");
1249             continue;
1250         }
1251         (void)PutBnContext(outContext); /* pair with initialize context */
1252     }
1253 }
1254 
ProcessCaDied(int32_t pid)1255 void CaDaemonService::ProcessCaDied(int32_t pid)
1256 {
1257     tloge("caDied: getCallingPid=%{public}d\n", pid);
1258     DaemonProcdata *outProcData = nullptr;
1259     {
1260         lock_guard<mutex> autoLock(mProcDataLock);
1261         outProcData = GetProcdataByPid(pid);
1262         if (outProcData == nullptr) {
1263             tloge("caDied: outProcdata[%{public}d] not in the list\n", pid);
1264             return;
1265         }
1266         ListRemoveEntry(&outProcData->procdataHead);
1267     }
1268 
1269     SendSigToTzdriver(pid);
1270     CleanProcDataForOneCa(outProcData);
1271     free(outProcData);
1272 }
1273 
SendSecfile(const char * path,int fd,FILE * fp,MessageParcel & reply)1274 TEEC_Result CaDaemonService::SendSecfile(const char *path, int fd, FILE *fp, MessageParcel &reply)
1275 {
1276     if (path == nullptr || fp == nullptr) {
1277         return TEEC_ERROR_BAD_PARAMETERS;
1278     }
1279     uint32_t ret = TEEC_SendSecfileInner(path, fd, fp);
1280     bool retTmp = reply.WriteUint32(ret);
1281     CHECK_ERR_RETURN(retTmp, true, TEEC_FAIL);
1282     return TEEC_SUCCESS;
1283 }
1284 
GetTeeVersion(MessageParcel & reply)1285 TEEC_Result CaDaemonService::GetTeeVersion(MessageParcel &reply)
1286 {
1287     bool retTmp = reply.WriteUint32(mTeeVersion);
1288     CHECK_ERR_RETURN(retTmp, true, TEEC_FAIL);
1289     return TEEC_SUCCESS;
1290 }
1291 } // namespace CaDaemon
1292 } // namespace OHOS
1293