1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "agent.h"
33 #include <securec.h>
34 #include "cmdmonitor.h"
35 #include "mailbox_mempool.h"
36 #include "smc.h"
37 #include "tc_client_sub_driver.h"
38 #include "tc_ns_log.h"
39 #include "teek_client_constants.h"
40 #include "tzdriver_compat.h"
41
42 #define HASH_FILE_MAX_SIZE (16 * 1024)
43 #define AGENT_BUFF_SIZE (4 * 1024)
44 #define AGENT_MAX 32
45 #define MAX_PATH_SIZE 512
46 #define PAGE_ORDER_RATIO 2
47
48 /* kernel agent, TeeAgentKernelOps list */
49 static struct list_head g_teeAgentList;
50
51 struct AgentControl {
52 spinlock_t lock;
53 struct list_head agentList; /* SmcEventData list */
54 };
55 static struct AgentControl g_agentControl;
56
57 typedef struct TagCaInfo {
58 char path[MAX_PATH_SIZE];
59 uint32_t uid;
60 uint32_t agentId;
61 } CaInfo;
62
63 static CaInfo g_allowedExtAgentCa[] = {
64 /* just for test in ENG version */
65 #ifdef DEF_ENG
66 {
67 "/vendor/bin/tee_test_agent",
68 0,
69 TEE_SECE_AGENT_ID,
70 },
71
72 #endif
73 };
74
IsAllowedAgentCa(const CaInfo * ca,bool checkAgentIdFlag)75 static int IsAllowedAgentCa(const CaInfo *ca, bool checkAgentIdFlag)
76 {
77 uint32_t i;
78 bool tmpCheckStatus = false;
79 CaInfo *tmpCa = g_allowedExtAgentCa;
80
81 if (!checkAgentIdFlag) {
82 for (i = 0; i < ARRAY_SIZE(g_allowedExtAgentCa); i++) {
83 if ((memcmp(ca->path, tmpCa->path, MAX_PATH_SIZE) == EOK) &&
84 (ca->uid == tmpCa->uid)) {
85 return AGENT_SUCCESS;
86 }
87 tmpCa++;
88 }
89 } else {
90 for (i = 0; i < ARRAY_SIZE(g_allowedExtAgentCa); i++) {
91 tmpCheckStatus = ((memcmp(ca->path, tmpCa->path, MAX_PATH_SIZE) == EOK) &&
92 (ca->uid == tmpCa->uid) && (ca->agentId == tmpCa->agentId));
93 if (tmpCheckStatus) {
94 return AGENT_SUCCESS;
95 }
96 tmpCa++;
97 }
98 }
99 tlogd("ca-uid is %u, ca_path is %s, agent id is %x\n", ca->uid, ca->path, ca->agentId);
100 return AGENT_FALSE;
101 }
102
GetCaPathAndUid(LosTaskCB * caTask,CaInfo * ca)103 static int GetCaPathAndUid(LosTaskCB *caTask, CaInfo *ca)
104 {
105 char *path = NULL;
106 int messageSize;
107 int ret = -1;
108 char *tPath = NULL;
109
110 tPath = malloc(MAX_PATH_SIZE);
111 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)tPath)) {
112 tloge("tPath malloc fail\n");
113 return -EPERM;
114 }
115
116 path = GetProcessPath(caTask, tPath, MAX_PATH_SIZE);
117 if (IS_ERR_OR_NULL(path)) {
118 ret = -ENOMEM;
119 tloge("get process path failed\n");
120 goto END;
121 }
122
123 messageSize = snprintf_s(ca->path, MAX_PATH_SIZE - 1, MAX_PATH_SIZE - 1, "%s", path);
124 ca->uid = GetTaskUid(caTask);
125 if (ca->uid < 0) {
126 free(tPath);
127 tPath = NULL;
128 return -EPERM;
129 }
130 tlogd("caTask->comm is %s, path is %s, ca uid is %u\n", caTask->taskName, path, ca->uid);
131
132 if (messageSize > 0) {
133 ret = 0;
134 }
135
136 END:
137 free(tPath);
138 tPath = NULL;
139 return ret;
140 }
141
CheckExtAgentAccess(LosTaskCB * caTask)142 int CheckExtAgentAccess(LosTaskCB *caTask)
143 {
144 int ret;
145 CaInfo agentCa = { {0}, 0 };
146
147 if (caTask == NULL) {
148 tloge("caTask is NULL.\n");
149 return -EPERM;
150 }
151
152 ret = GetCaPathAndUid(caTask, &agentCa);
153 if (ret) {
154 tloge("get cp path or uid failed.\n");
155 return ret;
156 }
157
158 ret = IsAllowedAgentCa(&agentCa, 0);
159 return ret;
160 }
161
CheckExtAgentAccessWithAgentId(LosTaskCB * caTask,uint32_t agentId)162 int CheckExtAgentAccessWithAgentId(LosTaskCB *caTask,
163 uint32_t agentId)
164 {
165 int ret;
166 CaInfo agentCa = {"", 0, 0};
167
168 if (caTask == NULL) {
169 tloge("caTask is NULL\n");
170 return -EPERM;
171 }
172
173 ret = GetCaPathAndUid(caTask, &agentCa);
174 if (ret) {
175 tloge("get cp path or uid failed\n");
176 return ret;
177 }
178 agentCa.agentId = agentId;
179 ret = IsAllowedAgentCa(&agentCa, 1);
180 return ret;
181 }
182
CheckNativeHashParam(uint8_t * inBuf,uint32_t * bufLen)183 static int CheckNativeHashParam(uint8_t *inBuf, uint32_t *bufLen)
184 {
185 if (inBuf == NULL) {
186 return AGENT_FALSE;
187 }
188 if (TcNsGetUid() != 0) {
189 tloge("It is a fake tee agent\n");
190 return -EACCES;
191 }
192 if (copy_from_user(bufLen, inBuf, sizeof(*bufLen))) {
193 tloge("copy from user failed\n");
194 return -EFAULT;
195 }
196 if (*bufLen > HASH_FILE_MAX_SIZE) {
197 tloge("ERROR: file size[0x%x] too big\n", *bufLen);
198 return AGENT_FALSE;
199 }
200 return 0;
201 }
202
TcNsSetNativeHash(unsigned long arg,unsigned int cmdId)203 int TcNsSetNativeHash(unsigned long arg, unsigned int cmdId)
204 {
205 int ret;
206 TcNsSmcCmd smcCmd = { {0}, 0 };
207 uint8_t *inBuf = (uint8_t *)(uintptr_t)arg;
208 uint32_t bufLen = 0;
209 uint8_t *bufToTee = NULL;
210 struct MbCmdPack *mbPack = NULL;
211
212 ret = CheckNativeHashParam(inBuf, &bufLen);
213 if (ret) {
214 return ret;
215 }
216
217 bufToTee = MailboxAlloc(bufLen, 0);
218 if (bufToTee == NULL) {
219 tloge("failed to alloc memory!\n");
220 return AGENT_FALSE;
221 }
222 if (copy_from_user(bufToTee, inBuf, bufLen)) {
223 tloge("copy from user failed\n");
224 MailboxFree(bufToTee);
225 return -EFAULT;
226 }
227 mbPack = MailboxAllocCmdPack();
228 if (mbPack == NULL) {
229 tloge("alloc cmd pack failed\n");
230 MailboxFree(bufToTee);
231 return -ENOMEM;
232 }
233 mbPack->operation.paramTypes = TEE_PARAM_TYPE_VALUE_INPUT |
234 (TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM);
235 mbPack->operation.params[TEE_PARAM_ONE].value.a =
236 (unsigned int)LOS_PaddrQuery(bufToTee);
237 mbPack->operation.params[TEE_PARAM_ONE].value.b = 0;
238 mbPack->operation.params[TEE_PARAM_TWO].value.a = bufLen;
239 smcCmd.globalCmd = true;
240 smcCmd.cmdId = cmdId;
241 smcCmd.operationPhys = LOS_PaddrQuery(&mbPack->operation);
242 smcCmd.operationHphys = 0;
243 ret = TcNsSmc(&smcCmd);
244 MailboxFree(bufToTee);
245 MailboxFree(mbPack);
246 bufToTee = NULL;
247 mbPack = NULL;
248 return ret;
249 }
250
TcNsLateInit(unsigned long arg)251 int TcNsLateInit(unsigned long arg)
252 {
253 int ret;
254 TcNsSmcCmd smcCmd = { {0}, 0 };
255 uint32_t index = (uint32_t)arg; // index is uint32, no truncate risk
256 struct MbCmdPack *mbPack = NULL;
257
258 if (TcNsGetUid() != 0) {
259 tloge("It is a fake tee agent\n");
260 return -EACCES;
261 }
262
263 mbPack = MailboxAllocCmdPack();
264 if (mbPack == NULL) {
265 tloge("alloc cmd pack failed\n");
266 return -ENOMEM;
267 }
268
269 mbPack->operation.paramTypes = TEE_PARAM_TYPE_VALUE_INPUT;
270 mbPack->operation.params[TEE_PARAM_ONE].value.a = index;
271
272 smcCmd.globalCmd = true;
273 smcCmd.cmdId = GLOBAL_CMD_ID_LATE_INIT;
274 smcCmd.operationPhys = LOS_PaddrQuery(&mbPack->operation);
275 smcCmd.operationHphys = 0;
276
277 ret = TcNsSmc(&smcCmd);
278
279 MailboxFree(mbPack);
280 mbPack = NULL;
281
282 return ret;
283 }
284
SendEventResponseSingle(const TcNsDevFile * devFile)285 void SendEventResponseSingle(const TcNsDevFile *devFile)
286 {
287 struct SmcEventData *eventData = NULL;
288 struct SmcEventData *tmp = NULL;
289 unsigned long flags;
290 unsigned int agentId = 0;
291
292 if (devFile == NULL) {
293 return;
294 }
295
296 spin_lock_irqsave(&g_agentControl.lock, flags);
297 list_for_each_entry_safe(eventData, tmp, &g_agentControl.agentList, head) {
298 if (eventData->owner == devFile) {
299 agentId = eventData->agentId;
300 break;
301 }
302 }
303 spin_unlock_irqrestore(&g_agentControl.lock, flags);
304 SendEventResponse(agentId);
305 return;
306 }
307
FindEventControl(unsigned int agentId)308 struct SmcEventData *FindEventControl(unsigned int agentId)
309 {
310 struct SmcEventData *eventData = NULL;
311 struct SmcEventData *tmpData = NULL;
312 unsigned long flags;
313
314 spin_lock_irqsave(&g_agentControl.lock, flags);
315 list_for_each_entry(eventData, &g_agentControl.agentList, head) {
316 if (eventData->agentId == agentId) {
317 tmpData = eventData;
318 GetAgentEvent(eventData);
319 break;
320 }
321 }
322 spin_unlock_irqrestore(&g_agentControl.lock, flags);
323
324 return tmpData;
325 }
326
UnmapAgentBuffer(struct SmcEventData * eventData)327 static void UnmapAgentBuffer(struct SmcEventData *eventData)
328 {
329 if (eventData == NULL) {
330 tloge("event data is NULL\n");
331 return;
332 }
333
334 if (IS_ERR_OR_NULL(eventData->agentBuffUser)) {
335 return;
336 }
337
338 if (LOS_UnMMap((VADDR_T)eventData->agentBuffUser, eventData->agentBuffSize) != 0) {
339 tloge("unmap failed\n");
340 }
341
342 eventData->agentBuffUser = NULL;
343 }
344
FreeEventControl(unsigned int agentId)345 static void FreeEventControl(unsigned int agentId)
346 {
347 struct SmcEventData *eventData = NULL;
348 struct SmcEventData *tmpEvent = NULL;
349 unsigned long flags;
350 bool find = false;
351
352 spin_lock_irqsave(&g_agentControl.lock, flags);
353 list_for_each_entry_safe(eventData, tmpEvent, &g_agentControl.agentList, head) {
354 if (eventData->agentId == agentId) {
355 list_del(&eventData->head);
356 find = true;
357 break;
358 }
359 }
360 spin_unlock_irqrestore(&g_agentControl.lock, flags);
361
362 if (find) {
363 UnmapAgentBuffer(eventData);
364
365 MailboxFree(eventData->agentBuffKernel);
366 eventData->agentBuffKernel = NULL;
367 PutAgentEvent(eventData);
368 }
369 }
370
InitAgentContext(unsigned int agentId,const TcNsSmcCmd * smcCmd,struct SmcEventData ** eventData)371 static int InitAgentContext(unsigned int agentId,
372 const TcNsSmcCmd *smcCmd,
373 struct SmcEventData **eventData)
374 {
375 if (eventData == NULL) {
376 return TEEC_ERROR_GENERIC;
377 }
378 *eventData = FindEventControl(agentId);
379 if (*eventData == NULL) {
380 tloge("agent %u not exist\n", agentId);
381 return TEEC_ERROR_GENERIC;
382 }
383 tlogd("AgentProcessWork(0x%x): returning client command", agentId);
384
385 #ifndef CONFIG_TEE_SMP
386 /* Keep a copy of the SMC cmd to return to TEE when the work is done */
387 if (memcpy_s(&((*eventData)->cmd), sizeof((*eventData)->cmd), smcCmd, sizeof(*smcCmd))) {
388 tloge("failed to memcpy_s smcCmd\n");
389 PutAgentEvent(*eventData);
390 return TEEC_ERROR_GENERIC;
391 }
392 ISB;
393 DSB;
394 #endif
395 return TEEC_SUCCESS;
396 }
397
WaitAgentResponse(struct SmcEventData * eventData)398 static int WaitAgentResponse(struct SmcEventData *eventData)
399 {
400 int ret = TEEC_SUCCESS;
401 bool answered = true;
402
403 do {
404 answered = true;
405 int r = wait_event_interruptible_timeout(eventData->caPendingWq,
406 atomic_read(&eventData->caRun), (long)(RESLEEP_TIMEOUT * HZ));
407 if (r != 0) {
408 continue;
409 }
410 /* if no kill signal, just resleep before agent wake */
411 if (SigkillPending(OsCurrTaskGet()) == 0) {
412 answered = false;
413 } else {
414 tloge("CA is killed, no need to wait agent response\n");
415 eventData->retFlag = 0;
416 ret = TEEC_ERROR_GENERIC;
417 }
418 } while (!answered);
419
420 return ret;
421 }
422
AgentProcessWork(const TcNsSmcCmd * smcCmd,unsigned int agentId)423 int AgentProcessWork(const TcNsSmcCmd *smcCmd, unsigned int agentId)
424 {
425 struct SmcEventData *eventData = NULL;
426 int ret = 0;
427
428 if (smcCmd == NULL) {
429 tloge("smcCmd is null\n");
430 return TEEC_ERROR_GENERIC;
431 }
432 if (InitAgentContext(agentId, smcCmd, &eventData) != TEEC_SUCCESS) {
433 return TEEC_ERROR_GENERIC;
434 }
435
436 #ifdef CONFIG_TEE_SMP
437 if (atomic_read(&eventData->agentReady) == AGENT_CRASHED) {
438 tloge("agent 0x%x is killed and restarting\n", agentId);
439 PutAgentEvent(eventData);
440 return TEEC_ERROR_GENERIC;
441 }
442 eventData->retFlag = 1;
443 /* Wake up the agent that will process the command */
444 tlogd("AgentProcessWork: wakeup the agent");
445 wake_up(&eventData->waitEventWq);
446 tlogd("agent 0x%x request, goto sleep, pe->run=%d\n",
447 agentId, atomic_read(&eventData->caRun));
448
449 ret = WaitAgentResponse(eventData);
450 atomic_set(&eventData->caRun, 0);
451 #endif
452
453 PutAgentEvent(eventData);
454 /*
455 * when agent work is done, reset cmd monitor time
456 * add agent call count, cause it's a new smc cmd.
457 */
458 CmdMonitorResetContext();
459 return ret;
460 }
461
IsAgentAlive(unsigned int agentId)462 int IsAgentAlive(unsigned int agentId)
463 {
464 struct SmcEventData *eventData = NULL;
465
466 eventData = FindEventControl(agentId);
467 if (eventData != NULL) {
468 PutAgentEvent(eventData);
469 return AGENT_ALIVE;
470 } else {
471 return AGENT_DEAD;
472 }
473 }
474
TcNsWaitEvent(unsigned int agentId)475 int TcNsWaitEvent(unsigned int agentId)
476 {
477 int ret = -EINVAL;
478 struct SmcEventData *eventData = NULL;
479
480 if ((TcNsGetUid() != 0) &&
481 CheckExtAgentAccessWithAgentId(OsCurrTaskGet(), agentId)) {
482 tloge("It is a fake tee agent\n");
483 return -EACCES;
484 }
485 tlogd("agent %u waits for command\n", agentId);
486 eventData = FindEventControl(agentId);
487 if (eventData != NULL) {
488 /* only when agent wait event, it's in ready state to work */
489 atomic_set(&(eventData->agentReady), AGENT_READY);
490 ret = wait_event_interruptible(eventData->waitEventWq, eventData->retFlag);
491 PutAgentEvent(eventData);
492 }
493
494 return ret;
495 }
496
TcNsSyncSysTime(const TcNsClientTime * tcNsTime)497 int TcNsSyncSysTime(const TcNsClientTime *tcNsTime)
498 {
499 TcNsSmcCmd smcCmd = { {0}, 0 };
500 int ret;
501 TcNsClientTime tmpTcNsTime = {0};
502 struct MbCmdPack *mbPack = NULL;
503
504 if (tcNsTime == NULL) {
505 tloge("tcNsTime is NULL input buffer\n");
506 return -EINVAL;
507 }
508 if (TcNsGetUid() != 0) {
509 tloge("It is a fake tee agent\n");
510 return TEEC_ERROR_GENERIC;
511 }
512 if (copy_from_user(&tmpTcNsTime, tcNsTime,
513 sizeof(tmpTcNsTime))) {
514 tloge("copy from user failed\n");
515 return -EFAULT;
516 }
517
518 mbPack = MailboxAllocCmdPack();
519 if (mbPack == NULL) {
520 tloge("alloc mb pack failed\n");
521 return -ENOMEM;
522 }
523
524 smcCmd.globalCmd = true;
525 smcCmd.cmdId = GLOBAL_CMD_ID_ADJUST_TIME;
526 smcCmd.errOrigin = tmpTcNsTime.seconds;
527 smcCmd.retVal = (int)tmpTcNsTime.millis;
528
529 ret = TcNsSmc(&smcCmd);
530 if (ret) {
531 tloge("tee adjust time failed, return error %x\n", ret);
532 }
533
534 MailboxFree(mbPack);
535 mbPack = NULL;
536
537 return ret;
538 }
539
CheckForSendEventResponse(unsigned int agentId)540 static struct SmcEventData *CheckForSendEventResponse(unsigned int agentId)
541 {
542 struct SmcEventData *eventData = FindEventControl(agentId);
543 bool tmpCheckStatus = false;
544
545 if (eventData == NULL) {
546 tloge("Can't get eventData\n");
547 return NULL;
548 }
549 tmpCheckStatus = ((TcNsGetUid() != 0) &&
550 CheckExtAgentAccessWithAgentId(OsCurrTaskGet(), agentId));
551 if (tmpCheckStatus) {
552 tloge("It is a fake tee agent\n");
553 PutAgentEvent(eventData);
554 return NULL;
555 }
556 return eventData;
557 }
558
ProcessSendEventResponse(struct SmcEventData * eventData)559 static int ProcessSendEventResponse(struct SmcEventData *eventData)
560 {
561 int ret = 0;
562 if (eventData->retFlag) {
563 eventData->retFlag = 0;
564 /* Send the command back to the TA session waiting for it */
565 #ifdef CONFIG_TEE_SMP
566 tlogd("agent wakeup ca\n");
567 atomic_set(&eventData->caRun, 1);
568 /* make sure reset working_ca before wakeup CA */
569 wake_up(&eventData->caPendingWq);
570 ret = 0;
571 #else
572 ret = TcNsPostSmc(&eventData->cmd);
573 #endif
574 }
575 return ret;
576 }
577
TcNsSendEventResponse(unsigned int agentId)578 int TcNsSendEventResponse(unsigned int agentId)
579 {
580 struct SmcEventData *eventData = NULL;
581 int ret;
582
583 eventData = CheckForSendEventResponse(agentId);
584 if (eventData == NULL) {
585 tlogd("agent %u pre-check failed\n", agentId);
586 return -1;
587 }
588 tlogd("agent %u sends answer back\n", agentId);
589 ret = ProcessSendEventResponse(eventData);
590 PutAgentEvent(eventData);
591 return ret;
592 }
593
SendEventResponse(unsigned int agentId)594 void SendEventResponse(unsigned int agentId)
595 {
596 struct SmcEventData *eventData = FindEventControl(agentId);
597 int ret;
598
599 if (eventData == NULL) {
600 tloge("Can't get eventData\n");
601 return;
602 }
603
604 tloge("agent 0x%x sends answer back\n", agentId);
605 atomic_set(&eventData->agentReady, AGENT_CRASHED);
606 ret = ProcessSendEventResponse(eventData);
607 PutAgentEvent(eventData);
608 if (ret) {
609 tloge("agent 0x%x sends answer back failed\n", agentId);
610 }
611 return;
612 }
613
InitEventDataForRestart(TcNsDevFile * devFile,struct SmcEventData * eventData)614 static void InitEventDataForRestart(TcNsDevFile *devFile,
615 struct SmcEventData *eventData)
616 {
617 eventData->retFlag = 0;
618 eventData->owner = devFile;
619 atomic_set(&eventData->agentReady, AGENT_REGISTERED);
620 init_waitqueue_head(&(eventData->waitEventWq));
621 init_waitqueue_head(&(eventData->sendResponseWq));
622 #ifdef CONFIG_TEE_SMP
623 init_waitqueue_head(&(eventData->caPendingWq));
624 atomic_set(&(eventData->caRun), 0);
625 #endif
626 return;
627 }
628
AllocAndInitEventData(TcNsDevFile * devFile,struct SmcEventData ** eventData,unsigned int agentId,UINTPTR * agentBuff,uint32_t agentBuffSize)629 static int AllocAndInitEventData(TcNsDevFile *devFile,
630 struct SmcEventData **eventData, unsigned int agentId,
631 UINTPTR *agentBuff, uint32_t agentBuffSize)
632 {
633 *agentBuff = (UINTPTR)MailboxAlloc(agentBuffSize, MB_FLAG_ZERO);
634 if (*agentBuff == 0) {
635 tloge("alloc agent buff failed\n");
636 return -ENOMEM;
637 }
638 *eventData = calloc(1, sizeof(**eventData));
639 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*eventData))) {
640 MailboxFree((void *)*agentBuff);
641 *agentBuff = 0;
642 *eventData = NULL;
643 tloge("alloc event data failed\n");
644 return -ENOMEM;
645 }
646 (*eventData)->agentId = agentId;
647 (*eventData)->retFlag = 0;
648 (*eventData)->agentBuffKernel = (void *)*agentBuff;
649 (*eventData)->agentBuffSize = agentBuffSize;
650 (*eventData)->owner = devFile;
651 atomic_set(&(*eventData)->agentReady, AGENT_REGISTERED);
652 init_waitqueue_head(&(*eventData)->waitEventWq);
653 init_waitqueue_head(&(*eventData)->sendResponseWq);
654 INIT_LIST_HEAD(&(*eventData)->head);
655 #ifdef CONFIG_TEE_SMP
656 init_waitqueue_head(&(*eventData)->caPendingWq);
657 atomic_set(&(*eventData)->caRun, 0);
658 #endif
659 return TEEC_SUCCESS;
660 }
661
IsBuiltInAgent(unsigned int agentId)662 static bool IsBuiltInAgent(unsigned int agentId)
663 {
664 bool checkValue = false;
665
666 checkValue = ((agentId == AGENT_FS_ID) ||
667 (agentId == AGENT_MISC_ID) ||
668 (agentId == AGENT_SOCKET_ID) ||
669 (agentId == SECFILE_LOAD_AGENT_ID));
670 return checkValue;
671 }
672
AgentBufferMap(unsigned long buffer,uint32_t size)673 static unsigned long AgentBufferMap(unsigned long buffer, uint32_t size)
674 {
675 int ret;
676
677 if (!IS_PAGE_ALIGNED(buffer) || !IS_PAGE_ALIGNED(size)) {
678 return -EFAULT;
679 }
680
681 vaddr_t userAddr = LOS_MMap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
682 if (IS_ERR_OR_NULL(userAddr)) {
683 goto ERR_OUT;
684 }
685
686 for (int i = 0; i < (size >> PAGE_SHIFT); i++) {
687 LosVmPage *page = LOS_VmPageGet(buffer + PAGE_SIZE * i);
688 if (page == NULL) {
689 goto ERR_OUT;
690 }
691 LOS_AtomicInc(&page->refCounts);
692 }
693
694 // agent buffer page is physically contiguous, so can entirety mmap
695 ret = remap_pfn_range(userAddr, buffer >> PAGE_SHIFT, size,
696 VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE);
697 if (ret) {
698 tloge("remap agent buffer failed, err=%d", ret);
699 goto ERR_OUT;
700 }
701 return userAddr;
702
703 ERR_OUT:
704 if (LOS_UnMMap(userAddr, size) != 0) {
705 tloge("munmap failed\n");
706 }
707 return -EFAULT;
708 }
709
IsValidAgent(unsigned int agentId,unsigned int bufferSize,bool userAgent)710 static bool IsValidAgent(unsigned int agentId,
711 unsigned int bufferSize, bool userAgent)
712 {
713 if (TcNsGetUid() != 0 &&
714 CheckExtAgentAccessWithAgentId(OsCurrTaskGet(), agentId)) {
715 tloge("It is a fake tee agent\n");
716 return false;
717 }
718
719 if (userAgent && (bufferSize > SZ_4K)) {
720 tloge("size: %u of user agent's shared mem is invalid\n",
721 bufferSize);
722 return false;
723 }
724 return true;
725 }
726
IsAgentAlreadyExist(unsigned int agentId,struct SmcEventData ** eventData,bool * findFlag)727 static void IsAgentAlreadyExist(unsigned int agentId,
728 struct SmcEventData **eventData, bool *findFlag)
729 {
730 unsigned long flags;
731 bool flag = false;
732 struct SmcEventData *agentNode = NULL;
733
734 spin_lock_irqsave(&g_agentControl.lock, flags);
735 list_for_each_entry(agentNode, &g_agentControl.agentList, head) {
736 if (agentNode->agentId == agentId) {
737 flag = true;
738 GetAgentEvent(agentNode);
739 break;
740 }
741 }
742 spin_unlock_irqrestore(&g_agentControl.lock, flags);
743 *findFlag = flag;
744 if (flag == true) {
745 *eventData = agentNode;
746 }
747 return;
748 }
749
AddEventNodeToList(struct SmcEventData * eventData)750 static void AddEventNodeToList(struct SmcEventData *eventData)
751 {
752 unsigned long flags;
753 spin_lock_irqsave(&g_agentControl.lock, flags);
754 list_add_tail(&eventData->head, &g_agentControl.agentList);
755 atomic_set(&eventData->usage, 1);
756 spin_unlock_irqrestore(&g_agentControl.lock, flags);
757 return;
758 }
759
RegisterAgentToTee(unsigned int agentId,UINTPTR agentBuff,uint32_t agentBuffSize)760 static int RegisterAgentToTee(unsigned int agentId, UINTPTR agentBuff,
761 uint32_t agentBuffSize)
762 {
763 int ret;
764 TcNsSmcCmd smcCmd = { {0}, 0 };
765 struct MbCmdPack *mbPack = NULL;
766
767 mbPack = MailboxAllocCmdPack();
768 if (mbPack == NULL) {
769 tloge("alloc mailbox failed\n");
770 return AGENT_FALSE;
771 }
772
773 mbPack->operation.paramTypes = TEE_PARAM_TYPE_VALUE_INPUT |
774 (TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM);
775 mbPack->operation.params[TEE_PARAM_ONE].value.a =
776 LOS_PaddrQuery((void *)agentBuff);
777 mbPack->operation.params[TEE_PARAM_ONE].value.b = 0;
778 mbPack->operation.params[TEE_PARAM_TWO].value.a = agentBuffSize;
779 smcCmd.globalCmd = true;
780 smcCmd.cmdId = GLOBAL_CMD_ID_REGISTER_AGENT;
781 smcCmd.operationPhys = LOS_PaddrQuery(&mbPack->operation);
782 smcCmd.operationHphys = 0;
783 smcCmd.agentId = agentId;
784
785 ret = TcNsSmc(&smcCmd);
786 /* mbPack should be released no matter what ret is */
787 MailboxFree(mbPack);
788 mbPack = NULL;
789
790 return ret;
791 }
792
ReleaseAgentResource(bool findFlag,struct SmcEventData * eventData,UINTPTR agentBuff)793 static void ReleaseAgentResource(bool findFlag, struct SmcEventData *eventData, UINTPTR agentBuff)
794 {
795 if (findFlag) {
796 PutAgentEvent(eventData); // match get action
797 } else {
798 free(eventData); // here eventData can never be NULL;
799 }
800
801 if (agentBuff != 0) {
802 MailboxFree((void *)agentBuff);
803 }
804 }
805
TcNsRegisterAgent(TcNsDevFile * devFile,unsigned int agentId,unsigned int bufferSize,void ** buffer,bool userAgent)806 int TcNsRegisterAgent(TcNsDevFile *devFile, unsigned int agentId,
807 unsigned int bufferSize, void **buffer, bool userAgent)
808 {
809 struct SmcEventData *eventData = NULL;
810 bool findFlag = false;
811 UINTPTR agentBuff = 0;
812 uint32_t sizeAlign;
813
814 if (buffer == NULL || devFile == NULL) {
815 return TEEC_ERROR_GENERIC;
816 }
817
818 if (IsValidAgent(agentId, bufferSize, userAgent) != true) {
819 return TEEC_ERROR_GENERIC;
820 }
821
822 sizeAlign = ALIGN(bufferSize, SZ_4K);
823
824 IsAgentAlreadyExist(agentId, &eventData, &findFlag);
825 /*
826 * We find the agent's eventData aready in agentList, it indicate agent
827 * didn't unregister normally, so the eventData will be reused.
828 */
829 if (findFlag) {
830 InitEventDataForRestart(devFile, eventData);
831 } else {
832 if (AllocAndInitEventData(devFile, &eventData,
833 agentId, &agentBuff, sizeAlign) != TEEC_SUCCESS) {
834 return TEEC_ERROR_GENERIC;
835 }
836 }
837
838 /* if the agent is first time or restart register, both case need a remap */
839 if (userAgent) {
840 eventData->agentBuffUser = (void *)(uintptr_t)AgentBufferMap(
841 LOS_PaddrQuery(eventData->agentBuffKernel),
842 eventData->agentBuffSize);
843 if (IS_ERR(eventData->agentBuffUser)) {
844 tloge("vm map agent buffer failed\n");
845 goto RELEASE_RSRC;
846 }
847 *buffer = eventData->agentBuffUser;
848 } else {
849 *buffer = eventData->agentBuffKernel;
850 }
851
852 /* findFlag is false means it's a new agent register */
853 if (findFlag == false) {
854 /* Obtain share memory which is released in TcNsUnregisterAgent */
855 if (RegisterAgentToTee(agentId, agentBuff, sizeAlign) != TEEC_SUCCESS) {
856 UnmapAgentBuffer(eventData);
857 goto RELEASE_RSRC;
858 }
859 AddEventNodeToList(eventData);
860 }
861 if (findFlag) {
862 PutAgentEvent(eventData); // match get action
863 }
864 return TEEC_SUCCESS;
865 RELEASE_RSRC:
866 ReleaseAgentResource(findFlag, eventData, agentBuff);
867 return TEEC_ERROR_GENERIC;
868 }
869
CheckForUnregisterAgent(unsigned int agentId)870 static int CheckForUnregisterAgent(unsigned int agentId)
871 {
872 bool checkValue = false;
873
874 checkValue = (TcNsGetUid() != 0);
875 if (checkValue) {
876 tloge("It is a fake tee agent\n");
877 return TEEC_ERROR_GENERIC;
878 }
879
880 checkValue = (IsBuiltInAgent(agentId) ||
881 agentId == TEE_RPMB_AGENT_ID);
882 if (checkValue) {
883 tloge("agent: 0x%x is not allowed to unregister\n", agentId);
884 return TEEC_ERROR_GENERIC;
885 }
886 return TEEC_SUCCESS;
887 }
888
IsThirdPartyAgent(unsigned int agentId)889 static bool IsThirdPartyAgent(unsigned int agentId)
890 {
891 uint32_t i;
892 CaInfo *tmpCa = g_allowedExtAgentCa;
893
894 for (i = 0; i < ARRAY_SIZE(g_allowedExtAgentCa); i++) {
895 if (tmpCa->agentId == agentId) {
896 return true;
897 }
898 tmpCa++;
899 }
900
901 return false;
902 }
903
TcNsUnregisterAgent(unsigned int agentId)904 int TcNsUnregisterAgent(unsigned int agentId)
905 {
906 struct SmcEventData *eventData = NULL;
907 int ret;
908 TcNsSmcCmd smcCmd = { {0}, 0 };
909 struct MbCmdPack *mbPack = NULL;
910
911 if (CheckForUnregisterAgent(agentId) != TEEC_SUCCESS) {
912 return TEEC_ERROR_GENERIC;
913 }
914 /* if third party itself trigger unregister agent
915 * we allow them to unregister.
916 */
917 if (IsThirdPartyAgent(agentId) != true) {
918 tloge("invalid agent id: 0x%x\n", agentId);
919 return TEEC_ERROR_GENERIC;
920 }
921
922 eventData = FindEventControl(agentId);
923 if (eventData == NULL || eventData->agentBuffKernel == NULL) {
924 tloge("agent is not found or kernelAddr is not allocated\n");
925 return TEEC_ERROR_GENERIC;
926 }
927
928 mbPack = MailboxAllocCmdPack();
929 if (mbPack == NULL) {
930 tloge("alloc mailbox failed\n");
931 PutAgentEvent(eventData);
932 return TEEC_ERROR_GENERIC;
933 }
934 mbPack->operation.paramTypes = TEE_PARAM_TYPE_VALUE_INPUT |
935 (TEE_PARAM_TYPE_VALUE_INPUT << TEE_PARAM_NUM);
936 mbPack->operation.params[TEE_PARAM_ONE].value.a =
937 LOS_PaddrQuery(eventData->agentBuffKernel);
938
939 mbPack->operation.params[TEE_PARAM_ONE].value.b = 0;
940 mbPack->operation.params[TEE_PARAM_TWO].value.a = SZ_4K;
941 smcCmd.globalCmd = true;
942 smcCmd.cmdId = GLOBAL_CMD_ID_UNREGISTER_AGENT;
943 smcCmd.operationPhys = LOS_PaddrQuery(&mbPack->operation);
944 smcCmd.operationHphys = 0;
945
946 smcCmd.agentId = agentId;
947 tlogd("Unregistering agent 0x%x\n", agentId);
948 ret = TcNsSmc(&smcCmd);
949 if (ret == TEEC_SUCCESS) {
950 FreeEventControl(agentId);
951 }
952 PutAgentEvent(eventData);
953 MailboxFree(mbPack);
954 return ret;
955 }
956
IsSystemAgent(const TcNsDevFile * devFile)957 bool IsSystemAgent(const TcNsDevFile *devFile)
958 {
959 struct SmcEventData *eventData = NULL;
960 struct SmcEventData *tmp = NULL;
961 bool systemAgent = false;
962 unsigned long flags;
963
964 if (devFile == NULL) {
965 return systemAgent;
966 }
967
968 spin_lock_irqsave(&g_agentControl.lock, flags);
969 list_for_each_entry_safe(eventData, tmp, &g_agentControl.agentList, head) {
970 if (eventData->owner == devFile) {
971 systemAgent = true;
972 break;
973 }
974 }
975 spin_unlock_irqrestore(&g_agentControl.lock, flags);
976
977 return systemAgent;
978 }
979
SendCrashedEventResponseAll(const TcNsDevFile * devFile)980 void SendCrashedEventResponseAll(const TcNsDevFile *devFile)
981 {
982 struct SmcEventData *eventData = NULL;
983 struct SmcEventData *tmp = NULL;
984 unsigned int agentId[AGENT_MAX] = {0};
985 unsigned int i = 0;
986 unsigned long flags;
987
988 spin_lock_irqsave(&g_agentControl.lock, flags);
989 list_for_each_entry_safe(eventData, tmp, &g_agentControl.agentList,
990 head) {
991 if ((eventData->owner == devFile) && (i < AGENT_MAX)) {
992 agentId[i++] = eventData->agentId;
993 }
994 }
995 spin_unlock_irqrestore(&g_agentControl.lock, flags);
996
997 for (i = 0; i < AGENT_MAX; i++) {
998 if (agentId[i]) {
999 SendEventResponse(agentId[i]);
1000 }
1001 }
1002
1003 return;
1004 }
1005
TeeAgentClearDevOwner(const TcNsDevFile * devFile)1006 void TeeAgentClearDevOwner(const TcNsDevFile *devFile)
1007 {
1008 struct SmcEventData *eventData = NULL;
1009 struct SmcEventData *tmp = NULL;
1010 unsigned long flags;
1011
1012 spin_lock_irqsave(&g_agentControl.lock, flags);
1013 list_for_each_entry_safe(eventData, tmp, &g_agentControl.agentList, head) {
1014 if (eventData->owner == devFile) {
1015 eventData->owner = NULL;
1016 break;
1017 }
1018 }
1019 spin_unlock_irqrestore(&g_agentControl.lock, flags);
1020 return;
1021 }
1022
DefTeeAgentWork(UINTPTR instance,int len)1023 static int DefTeeAgentWork(UINTPTR instance, int len)
1024 {
1025 int ret = 0;
1026 struct TeeAgentKernelOps *agentInstance = NULL;
1027
1028 if (len != sizeof(struct TeeAgentKernelOps)) {
1029 return ret;
1030 }
1031
1032 agentInstance = (struct TeeAgentKernelOps *)instance;
1033 while (!KthreadShouldStop()) {
1034 tlogd("%s agent loop++++\n", agentInstance->agentName);
1035 ret = TcNsWaitEvent(agentInstance->agentId);
1036 if (ret) {
1037 tloge("%s wait event fail\n",
1038 agentInstance->agentName);
1039 break;
1040 }
1041 if (agentInstance->teeAgentWork != NULL) {
1042 ret = agentInstance->teeAgentWork(agentInstance);
1043 if (ret) {
1044 tloge("%s agent work fail\n", agentInstance->agentName);
1045 }
1046 }
1047 ret = TcNsSendEventResponse(agentInstance->agentId);
1048 if (ret) {
1049 tloge("%s send event response fail\n",
1050 agentInstance->agentName);
1051 break;
1052 }
1053 tlogd("%s agent loop----\n", agentInstance->agentName);
1054 }
1055
1056 return ret;
1057 }
1058
DefTeeAgentRun(struct TeeAgentKernelOps * agentInstance)1059 static int DefTeeAgentRun(struct TeeAgentKernelOps *agentInstance)
1060 {
1061 TcNsDevFile dev = {0};
1062 int ret;
1063 char agentName[OS_TCB_NAME_LEN] = {0};
1064
1065 /* 1. Register agent buffer to TEE */
1066 ret = TcNsRegisterAgent(&dev, agentInstance->agentId,
1067 agentInstance->agentBuffSize, &agentInstance->agentBuff, false);
1068 if (ret) {
1069 tloge("register agent buffer fail,ret =0x%x\n", ret);
1070 ret = -1;
1071 goto OUT;
1072 }
1073
1074 /* 2. Create thread to run agent */
1075 ret = sprintf_s(agentName, OS_TCB_NAME_LEN, "agent_%s", agentInstance->agentName);
1076 if (ret == -1) {
1077 goto OUT;
1078 }
1079 agentInstance->agentThread =
1080 KthreadRun(DefTeeAgentWork, (void *)agentInstance, sizeof(struct TeeAgentKernelOps), agentName);
1081 if (IS_ERR_OR_NULL(agentInstance->agentThread)) {
1082 tloge("kthread create fail\n");
1083 ret = PTR_ERR(agentInstance->agentThread);
1084 agentInstance->agentThread = NULL;
1085 goto OUT;
1086 }
1087 return AGENT_SUCCESS;
1088
1089 OUT:
1090 return ret;
1091 }
1092
DefTeeAgentStop(struct TeeAgentKernelOps * agentInstance)1093 static int DefTeeAgentStop(struct TeeAgentKernelOps *agentInstance)
1094 {
1095 int ret;
1096
1097 if (TcNsSendEventResponse(agentInstance->agentId)) {
1098 tloge("failed to send response for agent %u\n",
1099 agentInstance->agentId);
1100 }
1101
1102 ret = TcNsUnregisterAgent(agentInstance->agentId);
1103 if (ret != 0) {
1104 tloge("failed to unregister agent %u\n",
1105 agentInstance->agentId);
1106 }
1107 if (!IS_ERR_OR_NULL(agentInstance->agentThread)) {
1108 KthreadStop(agentInstance->agentThread);
1109 }
1110
1111 return AGENT_SUCCESS;
1112 }
1113
1114 /* default kernel agent ops */
1115 static struct TeeAgentKernelOps g_defTeeAgentOps = {
1116 .agentName = "default",
1117 .agentId = 0,
1118 .teeAgentInit = NULL,
1119 .teeAgentRun = DefTeeAgentRun,
1120 .teeAgentWork = NULL,
1121 .teeAgentExit = NULL,
1122 .teeAgentStop = DefTeeAgentStop,
1123 .teeAgentCrashWork = NULL,
1124 .agentBuffSize = PAGE_SIZE,
1125 .list = LINUX_LIST_HEAD_INIT(g_defTeeAgentOps.list)
1126 };
1127
TeeAgentKernelInit(void)1128 static int TeeAgentKernelInit(void)
1129 {
1130 struct TeeAgentKernelOps *agentOps = NULL;
1131 int ret = 0;
1132 bool tmpCheckStatus = false;
1133
1134 list_for_each_entry(agentOps, &g_teeAgentList, list) {
1135 /* Check the agent validity */
1136 tmpCheckStatus = ((agentOps->agentId == 0) ||
1137 (agentOps->agentName == NULL) ||
1138 (agentOps->teeAgentWork == NULL));
1139 if (tmpCheckStatus) {
1140 tloge("agent is invalid\n");
1141 continue;
1142 }
1143 tlogd("ready to init %s agent, id=0x%x\n",
1144 agentOps->agentName, agentOps->agentId);
1145
1146 /* Set agent buff size */
1147 if (agentOps->agentBuffSize == 0) {
1148 agentOps->agentBuffSize = g_defTeeAgentOps.agentBuffSize;
1149 }
1150
1151 /* Initialize the agent */
1152 if (agentOps->teeAgentInit != NULL) {
1153 ret = agentOps->teeAgentInit(agentOps);
1154 } else if (g_defTeeAgentOps.teeAgentInit != NULL) {
1155 ret = g_defTeeAgentOps.teeAgentInit(agentOps);
1156 } else {
1157 tlogw("agent id %u has no init function\n",
1158 agentOps->agentId);
1159 }
1160 if (ret) {
1161 tloge("teeAgentInit %s failed\n",
1162 agentOps->agentName);
1163 continue;
1164 }
1165
1166 /* Run the agent */
1167 if (agentOps->teeAgentRun != NULL) {
1168 ret = agentOps->teeAgentRun(agentOps);
1169 } else if (g_defTeeAgentOps.teeAgentRun != NULL) {
1170 ret = g_defTeeAgentOps.teeAgentRun(agentOps);
1171 } else {
1172 tlogw("agent id %u has no run function\n",
1173 agentOps->agentId);
1174 }
1175 if (ret) {
1176 tloge("teeAgentRun %s failed\n",
1177 agentOps->agentName);
1178 if (agentOps->teeAgentExit != NULL) {
1179 agentOps->teeAgentExit(agentOps);
1180 }
1181 continue;
1182 }
1183 }
1184
1185 return AGENT_SUCCESS;
1186 }
1187
TeeAgentKernelExit(void)1188 static void TeeAgentKernelExit(void)
1189 {
1190 struct TeeAgentKernelOps *agentOps = NULL;
1191
1192 list_for_each_entry(agentOps, &g_teeAgentList, list) {
1193 /* Stop the agent */
1194 if (agentOps->teeAgentStop != NULL) {
1195 agentOps->teeAgentStop(agentOps);
1196 } else if (g_defTeeAgentOps.teeAgentStop != NULL) {
1197 g_defTeeAgentOps.teeAgentStop(agentOps);
1198 } else {
1199 tlogw("agent id %u has no stop function\n",
1200 agentOps->agentId);
1201 }
1202 /* Uninitialize the agent */
1203 if (agentOps->teeAgentExit != NULL) {
1204 agentOps->teeAgentExit(agentOps);
1205 } else if (g_defTeeAgentOps.teeAgentExit != NULL) {
1206 g_defTeeAgentOps.teeAgentExit(agentOps);
1207 } else {
1208 tlogw("agent id %u has no exit function\n",
1209 agentOps->agentId);
1210 }
1211 }
1212 }
1213
TeeAgentClearWork(TcNsClientContext * context,unsigned int devFileId)1214 int TeeAgentClearWork(TcNsClientContext *context,
1215 unsigned int devFileId)
1216 {
1217 struct TeeAgentKernelOps *agentOps = NULL;
1218
1219 list_for_each_entry(agentOps, &g_teeAgentList, list) {
1220 if (agentOps->teeAgentCrashWork != NULL) {
1221 agentOps->teeAgentCrashWork(agentOps,
1222 context, devFileId);
1223 }
1224 }
1225 return AGENT_SUCCESS;
1226 }
1227
1228 /* register kernel agent, for TeeAgentKernelInit load */
TeeAgentKernelRegister(struct TeeAgentKernelOps * newAgent)1229 int TeeAgentKernelRegister(struct TeeAgentKernelOps *newAgent)
1230 {
1231 if (newAgent == NULL) {
1232 return AGENT_FALSE;
1233 }
1234 INIT_LIST_HEAD(&newAgent->list);
1235 list_add_tail(&newAgent->list, &g_teeAgentList);
1236 return AGENT_SUCCESS;
1237 }
1238
AgentInit(void)1239 void AgentInit(void)
1240 {
1241 spin_lock_init(&g_agentControl.lock);
1242 INIT_LIST_HEAD(&g_agentControl.agentList);
1243 INIT_LIST_HEAD(&g_teeAgentList);
1244
1245 if (TeeAgentKernelInit() != AGENT_SUCCESS) {
1246 tloge("tee agent kernel init failed\n");
1247 }
1248
1249 return;
1250 }
1251
AgentExit(void)1252 int AgentExit(void)
1253 {
1254 TeeAgentKernelExit();
1255 return AGENT_SUCCESS;
1256 }
1257