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