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