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