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 ¶Decode, 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, ¶Decode);
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, ¶Decode);
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> ¬ify)
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> ¬ify)
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