• 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->callerIdentity.pid == pid) {
185                 procDataInList = tmp;
186                 break;
187             }
188         }
189     }
190     return procDataInList;
191 }
192 
CheckProcDataFdEmpty(DaemonProcdata * procData)193 static bool CheckProcDataFdEmpty(DaemonProcdata *procData)
194 {
195     int i;
196     for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
197         if (procData->cxtFd[i] != -1) {
198             return false;
199         }
200     }
201     return true;
202 }
203 
RemoveContextFromProcData(DaemonProcdata * outProcData,int32_t outContextFd)204 static void RemoveContextFromProcData(DaemonProcdata *outProcData, int32_t outContextFd)
205 {
206     int i;
207     for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
208         if (outContextFd == outProcData->cxtFd[i]) {
209             outProcData->cxtFd[i] = -1;
210             return;
211         }
212     }
213     tloge("can not find context in outProcdata\n");
214 }
215 
TidMutexLock(void)216 static int32_t TidMutexLock(void)
217 {
218     int lockRet = pthread_mutex_lock(&g_mutexTidList);
219     return lockRet;
220 }
221 
TidMutexUnlock(int lockRet)222 static void TidMutexUnlock(int lockRet)
223 {
224     int unlockRet;
225     if (lockRet != 0) {
226         tloge("not exe, mutex not in lock state. lock_ret = %" PUBLIC "d\n", lockRet);
227         return;
228     }
229     unlockRet = pthread_mutex_unlock(&g_mutexTidList);
230     if (unlockRet != 0) {
231         tloge("exe mutexUnlock error, ret = %" PUBLIC "d\n", unlockRet);
232     }
233 }
234 
SigUsr1Handler(int sign)235 static void SigUsr1Handler(int sign)
236 {
237     (void)sign;
238     return;
239 }
240 
RemoveTidFromList(TidData * tidData)241 static void RemoveTidFromList(TidData *tidData)
242 {
243     int retMutexLock = TidMutexLock();
244     if (retMutexLock) {
245         tloge("tid mutex lock failed\n");
246     }
247 
248     ListRemoveEntry(&tidData->tidHead);
249     TidMutexUnlock(retMutexLock);
250     free(tidData);
251     return;
252 }
253 
AddTidData(TidData ** tidData,int pid)254 static TEEC_Result AddTidData(TidData **tidData, int pid)
255 {
256     int mutexRet;
257     *tidData = static_cast<TidData *>(malloc(sizeof(TidData)));
258     if (*tidData == nullptr) {
259         tloge("tid_data malloc failed\n");
260         return TEEC_FAIL;
261     }
262     (*tidData)->tid = syscall(SYS_gettid);
263     (*tidData)->callingPid = pid;
264     ListInit(&(*tidData)->tidHead);
265 
266     mutexRet = TidMutexLock();
267     if (mutexRet != 0) {
268         tloge("tid mutex lock failed\n");
269         free(*tidData);
270         *tidData = nullptr;
271         return TEEC_FAIL;
272     }
273     ListInsertTail(&g_teecTidList, &(*tidData)->tidHead);
274     TidMutexUnlock(mutexRet);
275     tlogd("tid %" PUBLIC "d is sending command to TEE\n", (*tidData)->tid);
276     return TEEC_SUCCESS;
277 }
278 
SendSigToTzdriver(int pid)279 static void SendSigToTzdriver(int pid)
280 {
281     int mutexRet;
282     struct ListNode *ptr = nullptr;
283 
284     signal(SIGUSR1, SigUsr1Handler);
285     tlogd("ignore signal SIGUSR1!\n");
286 
287     mutexRet = TidMutexLock();
288     if (mutexRet != 0) {
289         tloge("tid mutex lock failed\n");
290         return;
291     }
292     if (!LIST_EMPTY(&g_teecTidList)) {
293         LIST_FOR_EACH(ptr, &g_teecTidList) {
294             TidData *tmp = LIST_ENTRY(ptr, TidData, tidHead);
295             if (tmp->callingPid == pid) {
296                 int ret = tgkill(getpid(), tmp->tid, SIGUSR1);
297                 tlogd("send signal SIGUSR1 to tid: %" PUBLIC "d! ret = %" PUBLIC "d\n", tmp->tid, ret);
298             }
299         }
300     }
301     TidMutexUnlock(mutexRet);
302 }
303 
IsValidContextWithoutLock(const TEEC_Context * context,const CallerIdentity & identity)304 bool CaDaemonService::IsValidContextWithoutLock(const TEEC_Context *context, const CallerIdentity &identity)
305 {
306     int i;
307     if (context == nullptr || context->fd < 0) {
308         tloge("invalid input context\n");
309         return false;
310     }
311 
312     DaemonProcdata *outProcData = GetProcdataByPid(identity.pid);
313     if (outProcData == nullptr) {
314         tloge("pid %" PUBLIC "d donnot have proc data in cadaemon\n", identity.pid);
315         return false;
316     }
317 
318     if (outProcData->callerIdentity.uid != identity.uid || outProcData->callerIdentity.tokenid != identity.tokenid) {
319         tloge("procdata with pid %" PUBLIC "d have mismatch uid or tokenid\n", identity.pid);
320         return false;
321     }
322 
323     for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
324         if (context->fd == outProcData->cxtFd[i]) {
325             return true;
326         }
327     }
328     return false;
329 }
330 
IsValidContext(const TEEC_Context * context,const CallerIdentity & identity)331 bool CaDaemonService::IsValidContext(const TEEC_Context *context, const CallerIdentity &identity)
332 {
333     lock_guard<mutex> autoLock(mProcDataLock);
334     return IsValidContextWithoutLock(context, identity);
335 }
336 
CallGetProcDataPtr(const CallerIdentity & identity)337 DaemonProcdata *CaDaemonService::CallGetProcDataPtr(const CallerIdentity &identity)
338 {
339     DaemonProcdata *outProcData = GetProcdataByPid(identity.pid);
340     if (outProcData != nullptr) {
341         if (outProcData->callerIdentity.uid != identity.uid ||
342             outProcData->callerIdentity.tokenid != identity.tokenid) {
343             tloge("procdata with pid %" PUBLIC "d have mismatch uid or tokenid\n", identity.pid);
344             return nullptr;
345         }
346     } else {
347         auto *procData = static_cast<DaemonProcdata *>(malloc(sizeof(DaemonProcdata)));
348         if (procData == nullptr) {
349             tloge("procdata malloc failed\n");
350             return nullptr;
351         }
352         (void)memset_s(procData, sizeof(DaemonProcdata), 0, sizeof(DaemonProcdata));
353 
354         for (int i = 0; i < MAX_CXTCNT_ONECA; i++) {
355             procData->cxtFd[i] = -1;
356         }
357         procData->callerIdentity.pid = identity.pid;
358         procData->callerIdentity.uid = identity.uid;
359         procData->callerIdentity.tokenid = identity.tokenid;
360         ListInit(&(procData->procdataHead));
361         ListInsertTail(&g_teecProcDataList, &procData->procdataHead);
362 
363         outProcData = procData;
364     }
365     return outProcData;
366 }
367 
SetContextToProcData(const CallerIdentity & identity,TEEC_ContextInner * outContext)368 TEEC_Result CaDaemonService::SetContextToProcData(const CallerIdentity &identity, TEEC_ContextInner *outContext)
369 {
370     int i;
371     {
372         lock_guard<mutex> autoLock(mProcDataLock);
373         DaemonProcdata *outProcData = CallGetProcDataPtr(identity);
374         if (outProcData == nullptr) {
375             tloge("proc data not found\n");
376             return TEEC_FAIL;
377         }
378 
379         for (i = 0; i < MAX_CXTCNT_ONECA; i++) {
380             if (outProcData->cxtFd[i] == -1) {
381                 outProcData->cxtFd[i] = outContext->fd;
382                 return TEEC_SUCCESS;
383             }
384         }
385     }
386 
387     tloge("the cnt of contexts in outProcData is already %" PUBLIC "d, please finalize some of them\n", i);
388     return TEEC_FAIL;
389 }
390 
PutBnContextAndReleaseFd(int pid,TEEC_ContextInner * outContext)391 void CaDaemonService::PutBnContextAndReleaseFd(int pid, TEEC_ContextInner *outContext)
392 {
393     if (outContext == nullptr) {
394         tlogd("put context is null\n");
395         return;
396     }
397 
398     int32_t contextFd = outContext->fd;
399     DaemonProcdata *outProcData = nullptr;
400 
401     lock_guard<mutex> autoLock(mProcDataLock);
402 
403     if (!PutBnContext(outContext)) {
404         return;
405     }
406 
407     tlogi("clear context success\n");
408 
409     outProcData = GetProcdataByPid(pid);
410     if (outProcData == nullptr) {
411         tloge("outProcdata is nullptr\n");
412         return;
413     }
414 
415     RemoveContextFromProcData(outProcData, contextFd);
416 
417     if (CheckProcDataFdEmpty(outProcData)) {
418         tlogi("ProcData is empty\n");
419         ListRemoveEntry(&outProcData->procdataHead);
420         free(outProcData);
421     } else {
422         tlogd("still have context not finalize in pid[%" PUBLIC "d]\n", pid);
423     }
424 }
425 
InitCaAuthInfo(CaAuthInfo * caInfo,const CallerIdentity & identity)426 static TEEC_Result InitCaAuthInfo(CaAuthInfo *caInfo, const CallerIdentity &identity)
427 {
428     caInfo->pid = identity.pid;
429     caInfo->uid = (unsigned int)(identity.uid);
430     static bool sendXmlSuccFlag = false;
431     /* Trans the system xml file to tzdriver */
432     if (!sendXmlSuccFlag) {
433         tlogd("cadaemon send system hash xml file\n");
434         if (TcuAuthentication(HASH_TYPE_SYSTEM) != 0) {
435             tloge("send system hash xml file failed\n");
436         } else {
437             sendXmlSuccFlag = true;
438         }
439     }
440 
441     TEEC_Result ret = (TEEC_Result)ConstructCaAuthInfo(identity.tokenid, caInfo);
442     if (ret != 0) {
443         tloge("construct ca auth info failed, ret %" PUBLIC "d\n", ret);
444         return TEEC_FAIL;
445     }
446 
447     return TEEC_SUCCESS;
448 }
449 
ReleaseContext(int pid,TEEC_ContextInner ** contextInner)450 void CaDaemonService::ReleaseContext(int pid, TEEC_ContextInner **contextInner)
451 {
452     TEEC_Context tempContext = { 0 };
453     /* After InitializeContextInner finished, ops_cnt is 2, contextInner wn't be released in PutBnContextAndReleaseFd */
454     PutBnContextAndReleaseFd(pid, *contextInner);
455     tempContext.fd = (*contextInner)->fd;
456     if (CallFinalizeContext(pid, &tempContext) < 0) {
457         tloge("CallFinalizeContext failed!\n");
458     }
459 
460     /* contextInner have been freed by finalize context */
461     *contextInner = nullptr;
462 }
463 
InitializeContext(const char * name,MessageParcel & reply)464 TEEC_Result CaDaemonService::InitializeContext(const char *name, MessageParcel &reply)
465 {
466     TEEC_Result ret = TEEC_FAIL;
467     CallerIdentity identity = {
468         IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingTokenID() };
469     TEEC_ContextInner *contextInner = (TEEC_ContextInner *)malloc(sizeof(*contextInner));
470     CaAuthInfo *caInfo = (CaAuthInfo *)malloc(sizeof(*caInfo));
471     tlogi("cadaemon service process initialize context, caller pid: %" PUBLIC "d\n", identity.pid);
472     if (contextInner == nullptr || caInfo == nullptr) {
473         tloge("malloc context and cainfo failed\n");
474         goto FREE_CONTEXT;
475     }
476     (void)memset_s(contextInner, sizeof(*contextInner), 0, sizeof(*contextInner));
477     (void)memset_s(caInfo, sizeof(*caInfo), 0, sizeof(*caInfo));
478 
479     if (InitCaAuthInfo(caInfo, identity) != TEEC_SUCCESS) {
480         goto FREE_CONTEXT;
481     }
482 
483     ret = TEEC_InitializeContextInner(contextInner, caInfo);
484     if (ret != TEEC_SUCCESS) {
485         goto FREE_CONTEXT;
486     }
487 
488     contextInner->callFromService = true;
489     ret = SetContextToProcData(identity, contextInner);
490     if (ret != TEEC_SUCCESS) {
491         goto RELEASE_CONTEXT;
492     }
493 
494     if (!reply.WriteInt32((int32_t)ret)) {
495         ret = TEEC_FAIL;
496         goto RELEASE_CONTEXT;
497     }
498 
499     if (!reply.WriteInt32(contextInner->fd)) {
500         ret = TEEC_FAIL;
501         goto RELEASE_CONTEXT;
502     }
503 
504     PutBnContextAndReleaseFd(identity.pid, contextInner); /* pair with ops_cnt++ when add to list */
505     goto END;
506 
507 RELEASE_CONTEXT:
508     ReleaseContext(identity.pid, &contextInner);
509 
510 FREE_CONTEXT:
511     if (contextInner != nullptr) {
512         free(contextInner);
513     }
514     LogException(ret, nullptr, TEEC_ORIGIN_API, TYPE_INITIALIZE_FAIL);
515 
516 END:
517     if (caInfo != nullptr) {
518         (void)memset_s(caInfo, sizeof(*caInfo), 0, sizeof(*caInfo));
519         free(caInfo);
520     }
521     return ret;
522 }
523 
FinalizeContext(TEEC_Context * context)524 TEEC_Result CaDaemonService::FinalizeContext(TEEC_Context *context)
525 {
526     if (context == nullptr) {
527         tloge("finalizeContext: invalid context!\n");
528         return TEEC_FAIL;
529     }
530 
531     CallerIdentity identity = {
532         IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingTokenID()
533     };
534     if (!IsValidContext(context, identity)) {
535         tloge("context and procdata have been released by service_died!\n");
536         return TEEC_FAIL;
537     }
538 
539     return CallFinalizeContext(identity.pid, context);
540 }
541 
CallFinalizeContext(int pid,const TEEC_Context * contextPtr)542 TEEC_Result CaDaemonService::CallFinalizeContext(int 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,const CallerIdentity & identity,TEEC_Session ** outSession,TEEC_ContextInner ** outContext)556 TEEC_Result CaDaemonService::CallGetBnContext(const TEEC_Context *inContext,
557     const CallerIdentity &identity, TEEC_Session **outSession, TEEC_ContextInner **outContext)
558 {
559     TEEC_ContextInner *tempContext = nullptr;
560 
561     if (!IsValidContext(inContext, identity)) {
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(identity.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     DecodePara paraDecode;
841     uint32_t returnOrigin = TEEC_ORIGIN_API;
842     TEEC_Session *outSession = nullptr;
843     TEEC_ContextInner *outContext = nullptr;
844     TidData *tidData = nullptr;
845     CallerIdentity identity = {
846         IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingTokenID() };
847     TaFileInfo taFile = { .taPath = nullptr, .taFp = nullptr };
848     tlogi("cadaemon service process open session, caller pid: %" PUBLIC "d\n", identity.pid);
849     TEEC_Result ret = CallGetBnContext(context, identity, &outSession, &outContext);
850     if (ret != TEEC_SUCCESS) {
851         goto ERROR;
852     }
853 
854     PrePareParmas(paraDecode, taFile, outContext, taPath, fd);
855 
856     ret = GetTeecOptMem(operation, optMemSize, optMem, &paraDecode);
857     if (ret != TEEC_SUCCESS) {
858         goto ERROR;
859     }
860 
861     if (AddTidData(&tidData, identity.pid) != TEEC_SUCCESS) {
862         ret = TEEC_FAIL;
863         goto ERROR;
864     }
865 
866     outSession->service_id = *destination;
867     outSession->session_id = 0;
868     ret = TEEC_OpenSessionInner(identity.pid, &taFile, outContext, outSession,
869         destination, connectionMethod, nullptr, operation, &returnOrigin);
870     RemoveTidFromList(tidData);
871     tidData = nullptr;
872 
873     PutAllocShrMem(paraDecode.shmInner, TEEC_PARAM_NUM);
874     PutBnContextAndReleaseFd(identity.pid, outContext); /* pairs with CallGetBnContext */
875 
876     if (!RecOpenReply(returnOrigin, ret, outSession, operation, reply)) {
877         goto ERROR;
878     }
879 
880     PutBnSession(outSession); /* pair with ops_cnt++ when add to list */
881     CloseTaFile(taFile, fd);
882 
883     return TEEC_SUCCESS;
884 
885 ERROR:
886     if (outSession != nullptr) {
887         free(outSession);
888         outSession = nullptr;
889     }
890 
891     CloseTaFile(taFile, fd);
892     LogException(ret, destination, returnOrigin, TYPE_OPEN_SESSION_FAIL);
893 
894     CHECK_ERR_RETURN(reply.WriteUint32(returnOrigin), true, TEEC_FAIL);
895     CHECK_ERR_RETURN(reply.WriteInt32((int32_t)ret), true, TEEC_FAIL);
896 
897     return TEEC_SUCCESS;
898 }
899 
CallGetBnSession(const CallerIdentity & identity,const TEEC_Context * inContext,const TEEC_Session * inSession,TEEC_ContextInner ** outContext,TEEC_Session ** outSession)900 TEEC_Result CaDaemonService::CallGetBnSession(const CallerIdentity &identity, const TEEC_Context *inContext,
901     const TEEC_Session *inSession, TEEC_ContextInner **outContext, TEEC_Session **outSession)
902 {
903     TEEC_ContextInner *tmpContext = nullptr;
904     TEEC_Session *tmpSession = nullptr;
905 
906     if ((inSession == nullptr) || (!IsValidContext(inContext, identity))) {
907         tloge("getSession: invalid context!\n");
908         return TEEC_FAIL;
909     }
910 
911     tmpContext = GetBnContext(inContext);
912     if (tmpContext == nullptr) {
913         tloge("getSession: no context found in service!\n");
914         return TEEC_ERROR_BAD_PARAMETERS;
915     }
916 
917     tmpSession = GetBnSession(inSession, tmpContext);
918     if (tmpSession == nullptr) {
919         tloge("getSession: no session found in service!\n");
920         PutBnContextAndReleaseFd(identity.pid, tmpContext);
921         return TEEC_ERROR_BAD_PARAMETERS;
922     }
923 
924     *outContext = tmpContext;
925     *outSession = tmpSession;
926     return TEEC_SUCCESS;
927 }
928 
InvokeCommand(TEEC_Context * context,TEEC_Session * session,uint32_t commandID,TEEC_Operation * operation,uint32_t optMemSize,sptr<Ashmem> & optMem,MessageParcel & reply)929 TEEC_Result CaDaemonService::InvokeCommand(TEEC_Context *context, TEEC_Session *session, uint32_t commandID,
930     TEEC_Operation *operation, uint32_t optMemSize, sptr<Ashmem> &optMem, MessageParcel &reply)
931 {
932     TEEC_ContextInner *outContext = nullptr;
933     TEEC_Session *outSession = nullptr;
934     TidData *tidData = nullptr;
935     uint32_t returnOrigin = TEEC_ORIGIN_API;
936     DecodePara paraDecode;
937     CallerIdentity identity = {
938         IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingTokenID()
939     };
940     tlogi("cadaemon service process invoke command, caller pid: %" PUBLIC "d\n", identity.pid);
941     TEEC_Result ret = CallGetBnSession(identity, context, session, &outContext, &outSession);
942     if (ret != TEEC_SUCCESS) {
943         tloge("get context and session failed\n");
944         goto END;
945     }
946 
947     (void)memset_s(&(paraDecode.shm), sizeof(paraDecode.shm), 0x00, sizeof(paraDecode.shm));
948     (void)memset_s(&(paraDecode.shmInner), sizeof(paraDecode.shmInner), 0x00, sizeof(paraDecode.shmInner));
949     paraDecode.contextInner = outContext;
950 
951     ret = GetTeecOptMem(operation, optMemSize, optMem, &paraDecode);
952     if (ret != TEEC_SUCCESS) {
953         PutBnSession(outSession);
954         PutBnContextAndReleaseFd(identity.pid, outContext);
955         goto END;
956     }
957 
958     if (AddTidData(&tidData, identity.pid) != TEEC_SUCCESS) {
959         PutBnSession(outSession);
960         PutBnContextAndReleaseFd(identity.pid, outContext);
961         goto END;
962     }
963     ret = TEEC_InvokeCommandInner(outContext, outSession, commandID, operation, &returnOrigin);
964     RemoveTidFromList(tidData);
965     tidData = nullptr;
966 
967     PutAllocShrMem(paraDecode.shmInner, TEEC_PARAM_NUM);
968     PutBnSession(outSession);
969     PutBnContextAndReleaseFd(identity.pid, outContext);
970 
971 END:
972     CHECK_ERR_RETURN(reply.WriteUint32(returnOrigin), true, TEEC_FAIL);
973     CHECK_ERR_RETURN(reply.WriteInt32((int32_t)ret), true, TEEC_FAIL);
974     CHECK_ERR_RETURN(WriteOperation(reply, operation), true, TEEC_FAIL);
975 
976     return TEEC_SUCCESS;
977 }
978 
CloseSession(TEEC_Session * session,TEEC_Context * context)979 TEEC_Result CaDaemonService::CloseSession(TEEC_Session *session, TEEC_Context *context)
980 {
981     CallerIdentity identity = {
982         IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingTokenID()
983     };
984     tlogi("cadaemon service process close session, caller pid: %" PUBLIC "d\n", identity.pid);
985     TidData *tidData = nullptr;
986     if ((session == nullptr) || (!IsValidContext(context, identity))) {
987         tloge("closeSession: invalid context!\n");
988         return TEEC_FAIL;
989     }
990 
991     TEEC_ContextInner *outContext = GetBnContext(context);
992     if (outContext == nullptr) {
993         tloge("closeSession: no context found in service!\n");
994         return TEEC_FAIL;
995     }
996 
997     TEEC_Session *outSession = FindAndRemoveSession(session, outContext);
998     if (outSession == nullptr) {
999         tloge("closeSession: no session found in service!\n");
1000         PutBnContextAndReleaseFd(identity.pid, outContext);
1001         return TEEC_FAIL;
1002     }
1003 
1004     if (AddTidData(&tidData, identity.pid) != TEEC_SUCCESS) {
1005         return TEEC_FAIL;
1006     }
1007     int32_t rc = TEEC_CloseSessionInner(outSession, outContext);
1008     if (rc != 0) {
1009         LogException(rc, &session->service_id, 0, TYPE_CLOSE_SESSION_FAIL);
1010     }
1011     RemoveTidFromList(tidData);
1012     tidData = nullptr;
1013 
1014     PutBnSession(outSession); /* pair with open session */
1015     PutBnContextAndReleaseFd(identity.pid, outContext);
1016     return TEEC_SUCCESS;
1017 }
1018 
RegisterSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem,MessageParcel & reply)1019 TEEC_Result CaDaemonService::RegisterSharedMemory(TEEC_Context *context,
1020     TEEC_SharedMemory *sharedMem, MessageParcel &reply)
1021 {
1022     TEEC_Result ret = TEEC_FAIL;
1023     TEEC_SharedMemoryInner *outShm = nullptr;
1024     TEEC_ContextInner *outContext = nullptr;
1025     bool writeRet = false;
1026     CallerIdentity identity = {
1027         IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingTokenID() };
1028     tlogi("cadaemon service process register shared memory, caller pid: %" PUBLIC "d\n", identity.pid);
1029     if ((sharedMem == nullptr) || (!IsValidContext(context, identity))) {
1030         tloge("registeMem: invalid context or sharedMem\n");
1031         goto ERROR_END;
1032     }
1033 
1034     outContext = GetBnContext(context);
1035     if (outContext == nullptr) {
1036         tloge("registeMem: no context found in service!\n");
1037         ret = TEEC_ERROR_BAD_PARAMETERS;
1038         goto ERROR_END;
1039     }
1040 
1041     outShm = static_cast<TEEC_SharedMemoryInner *>(malloc(sizeof(TEEC_SharedMemoryInner)));
1042     if (outShm == nullptr) {
1043         tloge("registeMem: outShm malloc failed.\n");
1044         goto ERROR_END;
1045     }
1046 
1047     (void)memset_s(outShm, sizeof(TEEC_SharedMemoryInner), 0, sizeof(TEEC_SharedMemoryInner));
1048 
1049     if (memcpy_s(outShm, sizeof(*outShm), sharedMem, sizeof(*sharedMem))) {
1050         tloge("registeMem: memcpy failed when copy data to shm, errno = %" PUBLIC "d!\n", errno);
1051         free(outShm);
1052         PutBnContextAndReleaseFd(identity.pid, outContext);
1053         goto ERROR_END;
1054     }
1055 
1056     ret = TEEC_RegisterSharedMemoryInner(outContext, outShm);
1057     if (ret != TEEC_SUCCESS) {
1058         free(outShm);
1059         PutBnContextAndReleaseFd(identity.pid, outContext);
1060         goto ERROR_END;
1061     }
1062 
1063     PutBnShrMem(outShm);
1064     PutBnContextAndReleaseFd(identity.pid, outContext);
1065 
1066     sharedMem->ops_cnt = outShm->ops_cnt;
1067     sharedMem->is_allocated = outShm->is_allocated;
1068 
1069     CHECK_ERR_RETURN(reply.WriteInt32((int32_t)ret), true, TEEC_FAIL);
1070 
1071     CHECK_ERR_RETURN(WriteSharedMem(reply, sharedMem), true, TEEC_FAIL);
1072 
1073     CHECK_ERR_RETURN(reply.WriteUint32(outShm->offset), true, TEEC_FAIL);
1074 
1075     return TEEC_SUCCESS;
1076 
1077 ERROR_END:
1078     writeRet = reply.WriteInt32((int32_t)ret);
1079     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
1080     return TEEC_SUCCESS;
1081 }
1082 
RecAllocReply(TEEC_Result ret,TEEC_SharedMemory * sharedMem,uint32_t offset,int32_t fd,MessageParcel & reply)1083 static bool RecAllocReply(TEEC_Result ret, TEEC_SharedMemory *sharedMem,
1084     uint32_t offset, int32_t fd, MessageParcel &reply)
1085 {
1086     bool writeRet = reply.WriteInt32((int32_t)ret);
1087     CHECK_ERR_RETURN(writeRet, true, writeRet);
1088 
1089     writeRet = WriteSharedMem(reply, sharedMem);
1090     CHECK_ERR_RETURN(writeRet, true, writeRet);
1091 
1092     writeRet = reply.WriteUint32(offset);
1093     CHECK_ERR_RETURN(writeRet, true, writeRet);
1094 
1095     writeRet = reply.WriteFileDescriptor(fd);
1096 
1097     return writeRet;
1098 }
1099 
AllocateSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem,MessageParcel & reply)1100 TEEC_Result CaDaemonService::AllocateSharedMemory(TEEC_Context *context,
1101     TEEC_SharedMemory *sharedMem, MessageParcel &reply)
1102 {
1103     TEEC_Result ret = TEEC_FAIL;
1104     bool writeRet = false;
1105     TEEC_ContextInner *outContext = nullptr;
1106     TEEC_SharedMemoryInner *outShm = nullptr;
1107     CallerIdentity identity = {
1108         IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingTokenID() };
1109     tlogi("cadaemon service process alloc shared memory, caller pid: %" PUBLIC "d\n", identity.pid);
1110     if ((sharedMem == nullptr) || (!IsValidContext(context, identity))) {
1111         tloge("allocateShamem: invalid context or sharedMem\n");
1112         goto ERROR;
1113     }
1114 
1115     outContext = GetBnContext(context);
1116     if (outContext == nullptr) {
1117         ret = TEEC_ERROR_BAD_PARAMETERS;
1118         goto ERROR;
1119     }
1120 
1121     outShm = (TEEC_SharedMemoryInner *)malloc(sizeof(TEEC_SharedMemoryInner));
1122     if (outShm == nullptr) {
1123         tloge("allocateShamem: outShm malloc failed\n");
1124         goto ERROR;
1125     }
1126 
1127     (void)memset_s(outShm, sizeof(*outShm), 0, sizeof(*outShm));
1128     (void)memcpy_s(outShm, sizeof(*outShm), sharedMem, sizeof(*sharedMem));
1129 
1130     ret = TEEC_AllocateSharedMemoryInner(outContext, outShm);
1131     if (ret != TEEC_SUCCESS) {
1132         goto ERROR;
1133     }
1134 
1135     sharedMem->ops_cnt = outShm->ops_cnt;
1136     sharedMem->is_allocated = outShm->is_allocated;
1137 
1138     writeRet = RecAllocReply(ret, sharedMem, outShm->offset, outContext->fd, reply);
1139     PutBnShrMem(outShm);
1140     PutBnContextAndReleaseFd(identity.pid, outContext);
1141     if (!writeRet) {
1142         ListRemoveEntry(&outShm->head);
1143         PutBnShrMem(outShm);
1144         return TEEC_FAIL;
1145     }
1146 
1147     return TEEC_SUCCESS;
1148 
1149 ERROR:
1150     if (outShm != nullptr) {
1151         free(outShm);
1152     }
1153     PutBnContextAndReleaseFd(identity.pid, outContext);
1154     writeRet = reply.WriteInt32((int32_t)ret);
1155     CHECK_ERR_RETURN(writeRet, true, TEEC_FAIL);
1156     return TEEC_SUCCESS;
1157 }
1158 
ReleaseSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem,uint32_t shmOffset,MessageParcel & reply)1159 TEEC_Result CaDaemonService::ReleaseSharedMemory(TEEC_Context *context,
1160     TEEC_SharedMemory *sharedMem, uint32_t shmOffset, MessageParcel &reply)
1161 {
1162     CallerIdentity identity = {
1163         IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingTokenID() };
1164     tlogi("cadaemon service process release shared memory, caller pid: %" PUBLIC "d\n", identity.pid);
1165     if ((sharedMem == nullptr) || (!IsValidContext(context, identity))) {
1166         tloge("releaseShamem: invalid context or sharedMem\n");
1167         return TEEC_ERROR_BAD_PARAMETERS;
1168     }
1169 
1170     TEEC_ContextInner *outContext = GetBnContext(context);
1171     if (outContext == nullptr) {
1172         tloge("releaseShamem: no context found in service!\n");
1173         return TEEC_ERROR_BAD_PARAMETERS;
1174     }
1175 
1176     TEEC_SharedMemoryInner outShm;
1177     (void)memset_s(&outShm, sizeof(TEEC_SharedMemoryInner), 0, sizeof(TEEC_SharedMemoryInner));
1178 
1179     if (memcpy_s(&outShm, sizeof(outShm), sharedMem, sizeof(*sharedMem))) {
1180         tloge("releaseShamem: memcpy failed when copy data to shm, errno = %" PUBLIC "d!\n", errno);
1181         return TEEC_FAIL;
1182     }
1183 
1184     outShm.offset = shmOffset;
1185     outShm.context = outContext;
1186     TEEC_ReleaseSharedMemoryInner(&outShm);
1187     PutBnContextAndReleaseFd(identity.pid, outContext);
1188     return TEEC_SUCCESS;
1189 }
1190 
PutAllocShrMem(TEEC_SharedMemoryInner * shmInner[],uint32_t shmNum)1191 void CaDaemonService::PutAllocShrMem(TEEC_SharedMemoryInner *shmInner[], uint32_t shmNum)
1192 {
1193     uint32_t paramCnt;
1194     for (paramCnt = 0; paramCnt < shmNum; paramCnt++) {
1195         if (shmInner[paramCnt] != nullptr) {
1196             PutBnShrMem(shmInner[paramCnt]);
1197         }
1198     }
1199 
1200     return;
1201 }
1202 
SetCallBack(const sptr<IRemoteObject> & notify)1203 int32_t CaDaemonService::SetCallBack(const sptr<IRemoteObject> &notify)
1204 {
1205     if (notify == nullptr) {
1206         tloge("notify is nullptr\n");
1207         return ERR_UNKNOWN_OBJECT;
1208     }
1209 
1210     /* register CA dead notify */
1211     pid_t pid = IPCSkeleton::GetCallingPid();
1212     tlogi("SetCallBack, ca pid=%" PUBLIC "d", pid);
1213 
1214     int32_t ret = AddClient(pid, notify);
1215     if (ret != 0) {
1216         tloge("client link to death failed, pid=%" PUBLIC "d", pid);
1217     }
1218     return ret;
1219 }
1220 
AddClient(pid_t pid,const sptr<IRemoteObject> & notify)1221 int32_t CaDaemonService::AddClient(pid_t pid, const sptr<IRemoteObject> &notify)
1222 {
1223     lock_guard<mutex> autoLock(mClientLock);
1224     size_t count = mClients.size();
1225     for (size_t index = 0; index < count; index++) {
1226         if (mClients[index]->GetMyPid() == pid) {
1227             tloge("client exist, pid=%" PUBLIC "d", pid);
1228             return ERR_NONE;
1229         }
1230     }
1231 
1232     sptr<Client> c = new (std::nothrow) Client(pid, notify, this);
1233     if (c == nullptr) {
1234         tloge("addclient:new client failed, pid=%" PUBLIC "d", pid);
1235         return ERR_UNKNOWN_REASON;
1236     }
1237     bool ret = notify->AddDeathRecipient(c);
1238     if (!ret) {
1239         tloge("addclient:link to death failed, pid=%" PUBLIC "d", pid);
1240         return ERR_UNKNOWN_REASON;
1241     }
1242     mClients.push_back(c);
1243     return ERR_NONE;
1244 }
1245 
~Client()1246 CaDaemonService::Client::~Client()
1247 {
1248     tloge("delete client come in, pid=%" PUBLIC "d", mPid);
1249 }
1250 
GetMyPid() const1251 pid_t CaDaemonService::Client::GetMyPid() const
1252 {
1253     return mPid;
1254 }
1255 
OnRemoteDied(const wptr<IRemoteObject> & deathNotify)1256 void CaDaemonService::Client::OnRemoteDied(const wptr<IRemoteObject> &deathNotify)
1257 {
1258     (void)deathNotify;
1259     tloge("teec client is died, pid=%" PUBLIC "d", mPid);
1260     vector<sptr<Client>>::iterator vec;
1261     if (mService != nullptr) {
1262         size_t index = 0;
1263         lock_guard<mutex> autoLock(mService->mClientLock);
1264         for (vec = mService->mClients.begin(); vec != mService->mClients.end();) {
1265             if (mService->mClients[index]->GetMyPid() == mPid) {
1266                 tloge("died teec client found, pid=%" PUBLIC "d", mPid);
1267                 /* release resources */
1268                 mService->ProcessCaDied(mPid);
1269                 vec = mService->mClients.erase(vec);
1270             } else {
1271                 ++vec;
1272                 index++;
1273             }
1274         }
1275     }
1276 }
1277 
CleanProcDataForOneCa(DaemonProcdata * procData)1278 void CaDaemonService::CleanProcDataForOneCa(DaemonProcdata *procData)
1279 {
1280     for (int i = 0; i < MAX_CXTCNT_ONECA; i++) {
1281         if (procData->cxtFd[i] == -1) {
1282             continue;
1283         }
1284 
1285         TEEC_Context context;
1286         context.fd = procData->cxtFd[i];
1287         procData->cxtFd[i] = -1;
1288 
1289         TEEC_ContextInner *outContext = FindAndRemoveBnContext(&context);
1290         if (outContext == nullptr) {
1291             tloge("no context found in service!\n");
1292             continue;
1293         }
1294         (void)PutBnContext(outContext); /* pair with initialize context */
1295     }
1296 }
1297 
ProcessCaDied(int32_t pid)1298 void CaDaemonService::ProcessCaDied(int32_t pid)
1299 {
1300     tloge("caDied: getCallingPid=%" PUBLIC "d\n", pid);
1301     DaemonProcdata *outProcData = nullptr;
1302     {
1303         lock_guard<mutex> autoLock(mProcDataLock);
1304         outProcData = GetProcdataByPid(pid);
1305         if (outProcData == nullptr) {
1306             tloge("caDied: outProcdata[%" PUBLIC "d] not in the list\n", pid);
1307             return;
1308         }
1309         ListRemoveEntry(&outProcData->procdataHead);
1310     }
1311 
1312     SendSigToTzdriver(pid);
1313     CleanProcDataForOneCa(outProcData);
1314     free(outProcData);
1315 }
1316 
SendSecfile(const char * path,int fd,FILE * fp,MessageParcel & reply)1317 TEEC_Result CaDaemonService::SendSecfile(const char *path, int fd, FILE *fp, MessageParcel &reply)
1318 {
1319     if (path == nullptr || fp == nullptr) {
1320         return TEEC_ERROR_BAD_PARAMETERS;
1321     }
1322     uint32_t ret = TEEC_SendSecfileInner(path, fd, fp);
1323     bool retTmp = reply.WriteUint32(ret);
1324     CHECK_ERR_RETURN(retTmp, true, TEEC_FAIL);
1325     return TEEC_SUCCESS;
1326 }
1327 
GetTeeVersion(MessageParcel & reply)1328 TEEC_Result CaDaemonService::GetTeeVersion(MessageParcel &reply)
1329 {
1330     bool retTmp = reply.WriteUint32(mTeeVersion);
1331     CHECK_ERR_RETURN(retTmp, true, TEEC_FAIL);
1332     return TEEC_SUCCESS;
1333 }
1334 } // namespace CaDaemon
1335 } // namespace OHOS
1336