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 "hm_liteipc.h"
33 #include "linux/kernel.h"
34 #include "fs/file.h"
35 #include "fs/driver.h"
36 #include "los_init.h"
37 #include "los_mp.h"
38 #include "los_mux.h"
39 #include "los_process_pri.h"
40 #include "los_sched_pri.h"
41 #include "los_spinlock.h"
42 #include "los_task_pri.h"
43 #include "los_vm_lock.h"
44 #include "los_vm_map.h"
45 #include "los_vm_page.h"
46 #include "los_vm_phys.h"
47 #include "los_hook.h"
48
49 #define USE_TASKID_AS_HANDLE 1
50 #define USE_MMAP 1
51 #define IPC_IO_DATA_MAX 8192UL
52 #define IPC_MSG_DATA_SZ_MAX (IPC_IO_DATA_MAX * sizeof(SpecialObj) / (sizeof(SpecialObj) + sizeof(size_t)))
53 #define IPC_MSG_OBJECT_NUM_MAX (IPC_MSG_DATA_SZ_MAX / sizeof(SpecialObj))
54
55 #define LITE_IPC_POOL_NAME "liteipc"
56 #define LITE_IPC_POOL_PAGE_MAX_NUM 64 /* 256KB */
57 #define LITE_IPC_POOL_PAGE_DEFAULT_NUM 16 /* 64KB */
58 #define LITE_IPC_POOL_MAX_SIZE (LITE_IPC_POOL_PAGE_MAX_NUM << PAGE_SHIFT)
59 #define LITE_IPC_POOL_DEFAULT_SIZE (LITE_IPC_POOL_PAGE_DEFAULT_NUM << PAGE_SHIFT)
60 #define LITE_IPC_POOL_UVADDR 0x10000000
61 #define INVAILD_ID (-1)
62
63 #define LITEIPC_TIMEOUT_MS 5000UL
64 #define LITEIPC_TIMEOUT_NS 5000000000ULL
65
66 typedef struct {
67 LOS_DL_LIST list;
68 VOID *ptr;
69 } IpcUsedNode;
70
71 STATIC LosMux g_serviceHandleMapMux;
72 #if (USE_TASKID_AS_HANDLE == 1)
73 STATIC HandleInfo g_cmsTask;
74 #else
75 STATIC HandleInfo g_serviceHandleMap[MAX_SERVICE_NUM];
76 #endif
77 STATIC LOS_DL_LIST g_ipcPendlist;
78
79 /* ipc lock */
80 SPIN_LOCK_INIT(g_ipcSpin);
81 #define IPC_LOCK(state) LOS_SpinLockSave(&g_ipcSpin, &(state))
82 #define IPC_UNLOCK(state) LOS_SpinUnlockRestore(&g_ipcSpin, state)
83
84 STATIC int LiteIpcOpen(struct file *filep);
85 STATIC int LiteIpcClose(struct file *filep);
86 STATIC int LiteIpcIoctl(struct file *filep, int cmd, unsigned long arg);
87 STATIC int LiteIpcMmap(struct file* filep, LosVmMapRegion *region);
88 STATIC UINT32 LiteIpcWrite(IpcContent *content);
89 STATIC UINT32 GetTid(UINT32 serviceHandle, UINT32 *taskID);
90 STATIC UINT32 HandleSpecialObjects(UINT32 dstTid, IpcListNode *node, BOOL isRollback);
91 STATIC ProcIpcInfo *LiteIpcPoolCreate(VOID);
92
93 STATIC const struct file_operations_vfs g_liteIpcFops = {
94 .open = LiteIpcOpen, /* open */
95 .close = LiteIpcClose, /* close */
96 .ioctl = LiteIpcIoctl, /* ioctl */
97 .mmap = LiteIpcMmap, /* mmap */
98 };
99
OsLiteIpcInit(VOID)100 LITE_OS_SEC_TEXT_INIT UINT32 OsLiteIpcInit(VOID)
101 {
102 UINT32 ret;
103 #if (USE_TASKID_AS_HANDLE == 1)
104 g_cmsTask.status = HANDLE_NOT_USED;
105 #else
106 (void)memset_s(g_serviceHandleMap, sizeof(g_serviceHandleMap), 0, sizeof(g_serviceHandleMap));
107 #endif
108 ret = LOS_MuxInit(&g_serviceHandleMapMux, NULL);
109 if (ret != LOS_OK) {
110 return ret;
111 }
112 ret = (UINT32)register_driver(LITEIPC_DRIVER, &g_liteIpcFops, LITEIPC_DRIVER_MODE, NULL);
113 if (ret != LOS_OK) {
114 PRINT_ERR("register lite_ipc driver failed:%d\n", ret);
115 }
116 LOS_ListInit(&(g_ipcPendlist));
117
118 return ret;
119 }
120
121 LOS_MODULE_INIT(OsLiteIpcInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
122
LiteIpcOpen(struct file * filep)123 LITE_OS_SEC_TEXT STATIC int LiteIpcOpen(struct file *filep)
124 {
125 LosProcessCB *pcb = OsCurrProcessGet();
126 if (pcb->ipcInfo != NULL) {
127 return 0;
128 }
129
130 pcb->ipcInfo = LiteIpcPoolCreate();
131 if (pcb->ipcInfo == NULL) {
132 return -ENOMEM;
133 }
134
135 return 0;
136 }
137
LiteIpcClose(struct file * filep)138 LITE_OS_SEC_TEXT STATIC int LiteIpcClose(struct file *filep)
139 {
140 return 0;
141 }
142
IsPoolMapped(ProcIpcInfo * ipcInfo)143 LITE_OS_SEC_TEXT STATIC BOOL IsPoolMapped(ProcIpcInfo *ipcInfo)
144 {
145 return (ipcInfo->pool.uvaddr != NULL) && (ipcInfo->pool.kvaddr != NULL) &&
146 (ipcInfo->pool.poolSize != 0);
147 }
148
DoIpcMmap(LosProcessCB * pcb,LosVmMapRegion * region)149 LITE_OS_SEC_TEXT STATIC INT32 DoIpcMmap(LosProcessCB *pcb, LosVmMapRegion *region)
150 {
151 UINT32 i;
152 INT32 ret = 0;
153 PADDR_T pa;
154 UINT32 uflags = VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_USER;
155 LosVmPage *vmPage = NULL;
156 VADDR_T uva = (VADDR_T)(UINTPTR)pcb->ipcInfo->pool.uvaddr;
157 VADDR_T kva = (VADDR_T)(UINTPTR)pcb->ipcInfo->pool.kvaddr;
158
159 (VOID)LOS_MuxAcquire(&pcb->vmSpace->regionMux);
160
161 for (i = 0; i < (region->range.size >> PAGE_SHIFT); i++) {
162 pa = LOS_PaddrQuery((VOID *)(UINTPTR)(kva + (i << PAGE_SHIFT)));
163 if (pa == 0) {
164 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
165 ret = -EINVAL;
166 break;
167 }
168 vmPage = LOS_VmPageGet(pa);
169 if (vmPage == NULL) {
170 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
171 ret = -EINVAL;
172 break;
173 }
174 STATUS_T err = LOS_ArchMmuMap(&pcb->vmSpace->archMmu, uva + (i << PAGE_SHIFT), pa, 1, uflags);
175 if (err < 0) {
176 ret = err;
177 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
178 break;
179 }
180 }
181 /* if any failure happened, rollback */
182 if (i != (region->range.size >> PAGE_SHIFT)) {
183 while (i--) {
184 pa = LOS_PaddrQuery((VOID *)(UINTPTR)(kva + (i << PAGE_SHIFT)));
185 vmPage = LOS_VmPageGet(pa);
186 (VOID)LOS_ArchMmuUnmap(&pcb->vmSpace->archMmu, uva + (i << PAGE_SHIFT), 1);
187 LOS_PhysPageFree(vmPage);
188 }
189 }
190
191 (VOID)LOS_MuxRelease(&pcb->vmSpace->regionMux);
192 return ret;
193 }
194
LiteIpcMmap(struct file * filep,LosVmMapRegion * region)195 LITE_OS_SEC_TEXT STATIC int LiteIpcMmap(struct file *filep, LosVmMapRegion *region)
196 {
197 int ret = 0;
198 LosVmMapRegion *regionTemp = NULL;
199 LosProcessCB *pcb = OsCurrProcessGet();
200 ProcIpcInfo *ipcInfo = pcb->ipcInfo;
201
202 if ((ipcInfo == NULL) || (region == NULL) || (region->range.size > LITE_IPC_POOL_MAX_SIZE) ||
203 (!LOS_IsRegionPermUserReadOnly(region)) || (!LOS_IsRegionFlagPrivateOnly(region))) {
204 ret = -EINVAL;
205 goto ERROR_REGION_OUT;
206 }
207 if (IsPoolMapped(ipcInfo)) {
208 return -EEXIST;
209 }
210 if (ipcInfo->pool.uvaddr != NULL) {
211 regionTemp = LOS_RegionFind(pcb->vmSpace, (VADDR_T)(UINTPTR)ipcInfo->pool.uvaddr);
212 if (regionTemp != NULL) {
213 (VOID)LOS_RegionFree(pcb->vmSpace, regionTemp);
214 }
215 }
216 ipcInfo->pool.uvaddr = (VOID *)(UINTPTR)region->range.base;
217 if (ipcInfo->pool.kvaddr != NULL) {
218 LOS_VFree(ipcInfo->pool.kvaddr);
219 ipcInfo->pool.kvaddr = NULL;
220 }
221 /* use vmalloc to alloc phy mem */
222 ipcInfo->pool.kvaddr = LOS_VMalloc(region->range.size);
223 if (ipcInfo->pool.kvaddr == NULL) {
224 ret = -ENOMEM;
225 goto ERROR_REGION_OUT;
226 }
227 /* do mmap */
228 ret = DoIpcMmap(pcb, region);
229 if (ret) {
230 goto ERROR_MAP_OUT;
231 }
232 /* ipc pool init */
233 if (LOS_MemInit(ipcInfo->pool.kvaddr, region->range.size) != LOS_OK) {
234 ret = -EINVAL;
235 goto ERROR_MAP_OUT;
236 }
237 ipcInfo->pool.poolSize = region->range.size;
238 return 0;
239 ERROR_MAP_OUT:
240 LOS_VFree(ipcInfo->pool.kvaddr);
241 ERROR_REGION_OUT:
242 if (ipcInfo != NULL) {
243 ipcInfo->pool.uvaddr = NULL;
244 ipcInfo->pool.kvaddr = NULL;
245 }
246 return ret;
247 }
248
LiteIpcPoolInit(ProcIpcInfo * ipcInfo)249 LITE_OS_SEC_TEXT_INIT STATIC UINT32 LiteIpcPoolInit(ProcIpcInfo *ipcInfo)
250 {
251 ipcInfo->pool.uvaddr = NULL;
252 ipcInfo->pool.kvaddr = NULL;
253 ipcInfo->pool.poolSize = 0;
254 ipcInfo->ipcTaskID = INVAILD_ID;
255 LOS_ListInit(&ipcInfo->ipcUsedNodelist);
256 return LOS_OK;
257 }
258
LiteIpcPoolCreate(VOID)259 LITE_OS_SEC_TEXT_INIT STATIC ProcIpcInfo *LiteIpcPoolCreate(VOID)
260 {
261 ProcIpcInfo *ipcInfo = LOS_MemAlloc(m_aucSysMem1, sizeof(ProcIpcInfo));
262 if (ipcInfo == NULL) {
263 return NULL;
264 }
265
266 (VOID)memset_s(ipcInfo, sizeof(ProcIpcInfo), 0, sizeof(ProcIpcInfo));
267
268 (VOID)LiteIpcPoolInit(ipcInfo);
269 return ipcInfo;
270 }
271
LiteIpcPoolReInit(const ProcIpcInfo * parent)272 LITE_OS_SEC_TEXT ProcIpcInfo *LiteIpcPoolReInit(const ProcIpcInfo *parent)
273 {
274 ProcIpcInfo *ipcInfo = LiteIpcPoolCreate();
275 if (ipcInfo == NULL) {
276 return NULL;
277 }
278
279 ipcInfo->pool.uvaddr = parent->pool.uvaddr;
280 ipcInfo->pool.kvaddr = NULL;
281 ipcInfo->pool.poolSize = 0;
282 ipcInfo->ipcTaskID = INVAILD_ID;
283 return ipcInfo;
284 }
285
LiteIpcPoolDelete(ProcIpcInfo * ipcInfo,UINT32 processID)286 STATIC VOID LiteIpcPoolDelete(ProcIpcInfo *ipcInfo, UINT32 processID)
287 {
288 UINT32 intSave;
289 IpcUsedNode *node = NULL;
290 if (ipcInfo->pool.kvaddr != NULL) {
291 LOS_VFree(ipcInfo->pool.kvaddr);
292 ipcInfo->pool.kvaddr = NULL;
293 IPC_LOCK(intSave);
294 while (!LOS_ListEmpty(&ipcInfo->ipcUsedNodelist)) {
295 node = LOS_DL_LIST_ENTRY(ipcInfo->ipcUsedNodelist.pstNext, IpcUsedNode, list);
296 LOS_ListDelete(&node->list);
297 free(node);
298 }
299 IPC_UNLOCK(intSave);
300 }
301 /* remove process access to service */
302 for (UINT32 i = 0; i < MAX_SERVICE_NUM; i++) {
303 if (ipcInfo->access[i] == TRUE) {
304 ipcInfo->access[i] = FALSE;
305 if (OS_TCB_FROM_TID(i)->ipcTaskInfo != NULL) {
306 OS_TCB_FROM_TID(i)->ipcTaskInfo->accessMap[processID] = FALSE;
307 }
308 }
309 }
310 }
311
LiteIpcPoolDestroy(UINT32 processID)312 LITE_OS_SEC_TEXT UINT32 LiteIpcPoolDestroy(UINT32 processID)
313 {
314 LosProcessCB *pcb = OS_PCB_FROM_PID(processID);
315
316 if (pcb->ipcInfo == NULL) {
317 return LOS_NOK;
318 }
319
320 LiteIpcPoolDelete(pcb->ipcInfo, pcb->processID);
321 LOS_MemFree(m_aucSysMem1, pcb->ipcInfo);
322 pcb->ipcInfo = NULL;
323 return LOS_OK;
324 }
325
LiteIpcTaskInit(VOID)326 LITE_OS_SEC_TEXT_INIT STATIC IpcTaskInfo *LiteIpcTaskInit(VOID)
327 {
328 IpcTaskInfo *taskInfo = LOS_MemAlloc((VOID *)m_aucSysMem1, sizeof(IpcTaskInfo));
329 if (taskInfo == NULL) {
330 return NULL;
331 }
332
333 (VOID)memset_s(taskInfo, sizeof(IpcTaskInfo), 0, sizeof(IpcTaskInfo));
334 LOS_ListInit(&taskInfo->msgListHead);
335 return taskInfo;
336 }
337
338 /* Only when kernenl no longer access ipc node content, can user free the ipc node */
EnableIpcNodeFreeByUser(UINT32 processID,VOID * buf)339 LITE_OS_SEC_TEXT STATIC VOID EnableIpcNodeFreeByUser(UINT32 processID, VOID *buf)
340 {
341 UINT32 intSave;
342 ProcIpcInfo *ipcInfo = OS_PCB_FROM_PID(processID)->ipcInfo;
343 IpcUsedNode *node = (IpcUsedNode *)malloc(sizeof(IpcUsedNode));
344 if (node != NULL) {
345 node->ptr = buf;
346 IPC_LOCK(intSave);
347 LOS_ListAdd(&ipcInfo->ipcUsedNodelist, &node->list);
348 IPC_UNLOCK(intSave);
349 }
350 }
351
LiteIpcNodeAlloc(UINT32 processID,UINT32 size)352 LITE_OS_SEC_TEXT STATIC VOID *LiteIpcNodeAlloc(UINT32 processID, UINT32 size)
353 {
354 VOID *ptr = LOS_MemAlloc(OS_PCB_FROM_PID(processID)->ipcInfo->pool.kvaddr, size);
355 PRINT_INFO("LiteIpcNodeAlloc pid:%d, pool:%x buf:%x size:%d\n",
356 processID, OS_PCB_FROM_PID(processID)->ipcInfo->pool.kvaddr, ptr, size);
357 return ptr;
358 }
359
LiteIpcNodeFree(UINT32 processID,VOID * buf)360 LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcNodeFree(UINT32 processID, VOID *buf)
361 {
362 PRINT_INFO("LiteIpcNodeFree pid:%d, pool:%x buf:%x\n",
363 processID, OS_PCB_FROM_PID(processID)->ipcInfo->pool.kvaddr, buf);
364 return LOS_MemFree(OS_PCB_FROM_PID(processID)->ipcInfo->pool.kvaddr, buf);
365 }
366
IsIpcNode(UINT32 processID,const VOID * buf)367 LITE_OS_SEC_TEXT STATIC BOOL IsIpcNode(UINT32 processID, const VOID *buf)
368 {
369 IpcUsedNode *node = NULL;
370 UINT32 intSave;
371 ProcIpcInfo *ipcInfo = OS_PCB_FROM_PID(processID)->ipcInfo;
372 IPC_LOCK(intSave);
373 LOS_DL_LIST_FOR_EACH_ENTRY(node, &ipcInfo->ipcUsedNodelist, IpcUsedNode, list) {
374 if (node->ptr == buf) {
375 LOS_ListDelete(&node->list);
376 IPC_UNLOCK(intSave);
377 free(node);
378 return TRUE;
379 }
380 }
381 IPC_UNLOCK(intSave);
382 return FALSE;
383 }
384
GetIpcUserAddr(UINT32 processID,INTPTR kernelAddr)385 LITE_OS_SEC_TEXT STATIC INTPTR GetIpcUserAddr(UINT32 processID, INTPTR kernelAddr)
386 {
387 IpcPool pool = OS_PCB_FROM_PID(processID)->ipcInfo->pool;
388 INTPTR offset = (INTPTR)(pool.uvaddr) - (INTPTR)(pool.kvaddr);
389 return kernelAddr + offset;
390 }
391
GetIpcKernelAddr(UINT32 processID,INTPTR userAddr)392 LITE_OS_SEC_TEXT STATIC INTPTR GetIpcKernelAddr(UINT32 processID, INTPTR userAddr)
393 {
394 IpcPool pool = OS_PCB_FROM_PID(processID)->ipcInfo->pool;
395 INTPTR offset = (INTPTR)(pool.uvaddr) - (INTPTR)(pool.kvaddr);
396 return userAddr - offset;
397 }
398
CheckUsedBuffer(const VOID * node,IpcListNode ** outPtr)399 LITE_OS_SEC_TEXT STATIC UINT32 CheckUsedBuffer(const VOID *node, IpcListNode **outPtr)
400 {
401 VOID *ptr = NULL;
402 LosProcessCB *pcb = OsCurrProcessGet();
403 IpcPool pool = pcb->ipcInfo->pool;
404 if ((node == NULL) || ((INTPTR)node < (INTPTR)(pool.uvaddr)) ||
405 ((INTPTR)node > (INTPTR)(pool.uvaddr) + pool.poolSize)) {
406 return -EINVAL;
407 }
408 ptr = (VOID *)GetIpcKernelAddr(pcb->processID, (INTPTR)(node));
409 if (IsIpcNode(pcb->processID, ptr) != TRUE) {
410 return -EFAULT;
411 }
412 *outPtr = (IpcListNode *)ptr;
413 return LOS_OK;
414 }
415
GetTid(UINT32 serviceHandle,UINT32 * taskID)416 LITE_OS_SEC_TEXT STATIC UINT32 GetTid(UINT32 serviceHandle, UINT32 *taskID)
417 {
418 if (serviceHandle >= MAX_SERVICE_NUM) {
419 return -EINVAL;
420 }
421 (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER);
422 #if (USE_TASKID_AS_HANDLE == 1)
423 *taskID = serviceHandle ? serviceHandle : g_cmsTask.taskID;
424 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
425 return LOS_OK;
426 #else
427 if (g_serviceHandleMap[serviceHandle].status == HANDLE_REGISTED) {
428 *taskID = g_serviceHandleMap[serviceHandle].taskID;
429 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
430 return LOS_OK;
431 }
432 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
433 return -EINVAL;
434 #endif
435 }
436
GenerateServiceHandle(UINT32 taskID,HandleStatus status,UINT32 * serviceHandle)437 LITE_OS_SEC_TEXT STATIC UINT32 GenerateServiceHandle(UINT32 taskID, HandleStatus status, UINT32 *serviceHandle)
438 {
439 (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER);
440 #if (USE_TASKID_AS_HANDLE == 1)
441 *serviceHandle = taskID ? taskID : LOS_CurTaskIDGet(); /* if taskID is 0, return curTaskID */
442 if (*serviceHandle != g_cmsTask.taskID) {
443 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
444 return LOS_OK;
445 }
446 #else
447 for (UINT32 i = 1; i < MAX_SERVICE_NUM; i++) {
448 if (g_serviceHandleMap[i].status == HANDLE_NOT_USED) {
449 g_serviceHandleMap[i].taskID = taskID;
450 g_serviceHandleMap[i].status = status;
451 *serviceHandle = i;
452 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
453 return LOS_OK;
454 }
455 }
456 #endif
457 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
458 return -EINVAL;
459 }
460
RefreshServiceHandle(UINT32 serviceHandle,UINT32 result)461 LITE_OS_SEC_TEXT STATIC VOID RefreshServiceHandle(UINT32 serviceHandle, UINT32 result)
462 {
463 #if (USE_TASKID_AS_HANDLE == 0)
464 (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER);
465 if ((result == LOS_OK) && (g_serviceHandleMap[serviceHandle].status == HANDLE_REGISTING)) {
466 g_serviceHandleMap[serviceHandle].status = HANDLE_REGISTED;
467 } else {
468 g_serviceHandleMap[serviceHandle].status = HANDLE_NOT_USED;
469 }
470 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
471 #endif
472 }
473
AddServiceAccess(UINT32 taskID,UINT32 serviceHandle)474 LITE_OS_SEC_TEXT STATIC UINT32 AddServiceAccess(UINT32 taskID, UINT32 serviceHandle)
475 {
476 UINT32 serviceTid = 0;
477 UINT32 ret = GetTid(serviceHandle, &serviceTid);
478 if (ret != LOS_OK) {
479 PRINT_ERR("Liteipc AddServiceAccess GetTid failed\n");
480 return ret;
481 }
482 LosTaskCB *tcb = OS_TCB_FROM_TID(serviceTid);
483 UINT32 processID = OS_TCB_FROM_TID(taskID)->processID;
484 LosProcessCB *pcb = OS_PCB_FROM_PID(processID);
485 if ((tcb->ipcTaskInfo == NULL) || (pcb->ipcInfo == NULL)) {
486 PRINT_ERR("Liteipc AddServiceAccess ipc not create! pid %u tid %u\n", processID, tcb->taskID);
487 return -EINVAL;
488 }
489 tcb->ipcTaskInfo->accessMap[processID] = TRUE;
490 pcb->ipcInfo->access[serviceTid] = TRUE;
491 return LOS_OK;
492 }
493
HasServiceAccess(UINT32 serviceHandle)494 LITE_OS_SEC_TEXT STATIC BOOL HasServiceAccess(UINT32 serviceHandle)
495 {
496 UINT32 serviceTid = 0;
497 UINT32 curProcessID = LOS_GetCurrProcessID();
498 UINT32 ret;
499 if (serviceHandle >= MAX_SERVICE_NUM) {
500 return FALSE;
501 }
502 if (serviceHandle == 0) {
503 return TRUE;
504 }
505 ret = GetTid(serviceHandle, &serviceTid);
506 if (ret != LOS_OK) {
507 PRINT_ERR("Liteipc HasServiceAccess GetTid failed\n");
508 return FALSE;
509 }
510 if (OS_TCB_FROM_TID(serviceTid)->processID == curProcessID) {
511 return TRUE;
512 }
513
514 if (OS_TCB_FROM_TID(serviceTid)->ipcTaskInfo == NULL) {
515 return FALSE;
516 }
517
518 return OS_TCB_FROM_TID(serviceTid)->ipcTaskInfo->accessMap[curProcessID];
519 }
520
SetIpcTask(VOID)521 LITE_OS_SEC_TEXT STATIC UINT32 SetIpcTask(VOID)
522 {
523 if (OsCurrProcessGet()->ipcInfo->ipcTaskID == INVAILD_ID) {
524 OsCurrProcessGet()->ipcInfo->ipcTaskID = LOS_CurTaskIDGet();
525 return OsCurrProcessGet()->ipcInfo->ipcTaskID;
526 }
527 PRINT_ERR("Liteipc curprocess %d IpcTask already set!\n", OsCurrProcessGet()->processID);
528 return -EINVAL;
529 }
530
IsIpcTaskSet(VOID)531 LITE_OS_SEC_TEXT BOOL IsIpcTaskSet(VOID)
532 {
533 if (OsCurrProcessGet()->ipcInfo->ipcTaskID == INVAILD_ID) {
534 return FALSE;
535 }
536 return TRUE;
537 }
538
GetIpcTaskID(UINT32 processID,UINT32 * ipcTaskID)539 LITE_OS_SEC_TEXT STATIC UINT32 GetIpcTaskID(UINT32 processID, UINT32 *ipcTaskID)
540 {
541 if (OS_PCB_FROM_PID(processID)->ipcInfo->ipcTaskID == INVAILD_ID) {
542 return LOS_NOK;
543 }
544 *ipcTaskID = OS_PCB_FROM_PID(processID)->ipcInfo->ipcTaskID;
545 return LOS_OK;
546 }
547
SendDeathMsg(UINT32 processID,UINT32 serviceHandle)548 LITE_OS_SEC_TEXT STATIC UINT32 SendDeathMsg(UINT32 processID, UINT32 serviceHandle)
549 {
550 UINT32 ipcTaskID;
551 UINT32 ret;
552 IpcContent content;
553 IpcMsg msg;
554 LosProcessCB *pcb = OS_PCB_FROM_PID(processID);
555
556 if (pcb->ipcInfo == NULL) {
557 return -EINVAL;
558 }
559
560 pcb->ipcInfo->access[serviceHandle] = FALSE;
561
562 ret = GetIpcTaskID(processID, &ipcTaskID);
563 if (ret != LOS_OK) {
564 return -EINVAL;
565 }
566 content.flag = SEND;
567 content.outMsg = &msg;
568 (void)memset_s(content.outMsg, sizeof(IpcMsg), 0, sizeof(IpcMsg));
569 content.outMsg->type = MT_DEATH_NOTIFY;
570 content.outMsg->target.handle = ipcTaskID;
571 content.outMsg->target.token = serviceHandle;
572 content.outMsg->code = 0;
573 return LiteIpcWrite(&content);
574 }
575
LiteIpcRemoveServiceHandle(UINT32 taskID)576 LITE_OS_SEC_TEXT VOID LiteIpcRemoveServiceHandle(UINT32 taskID)
577 {
578 UINT32 j;
579 LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
580 IpcTaskInfo *ipcTaskInfo = taskCB->ipcTaskInfo;
581 if (ipcTaskInfo == NULL) {
582 return;
583 }
584
585 #if (USE_TASKID_AS_HANDLE == 1)
586
587 UINT32 intSave;
588 LOS_DL_LIST *listHead = NULL;
589 LOS_DL_LIST *listNode = NULL;
590 IpcListNode *node = NULL;
591 UINT32 processID = taskCB->processID;
592
593 listHead = &(ipcTaskInfo->msgListHead);
594 do {
595 SCHEDULER_LOCK(intSave);
596 if (LOS_ListEmpty(listHead)) {
597 SCHEDULER_UNLOCK(intSave);
598 break;
599 } else {
600 listNode = LOS_DL_LIST_FIRST(listHead);
601 LOS_ListDelete(listNode);
602 node = LOS_DL_LIST_ENTRY(listNode, IpcListNode, listNode);
603 SCHEDULER_UNLOCK(intSave);
604 (VOID)HandleSpecialObjects(taskCB->taskID, node, TRUE);
605 (VOID)LiteIpcNodeFree(processID, (VOID *)node);
606 }
607 } while (1);
608
609 ipcTaskInfo->accessMap[processID] = FALSE;
610 for (j = 0; j < MAX_SERVICE_NUM; j++) {
611 if (ipcTaskInfo->accessMap[j] == TRUE) {
612 ipcTaskInfo->accessMap[j] = FALSE;
613 (VOID)SendDeathMsg(j, taskCB->taskID);
614 }
615 }
616 #else
617 (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER);
618 for (UINT32 i = 1; i < MAX_SERVICE_NUM; i++) {
619 if ((g_serviceHandleMap[i].status != HANDLE_NOT_USED) && (g_serviceHandleMap[i].taskID == taskCB->taskID)) {
620 g_serviceHandleMap[i].status = HANDLE_NOT_USED;
621 g_serviceHandleMap[i].taskID = INVAILD_ID;
622 break;
623 }
624 }
625 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
626 /* run deathHandler */
627 if (i < MAX_SERVICE_NUM) {
628 for (j = 0; j < MAX_SERVICE_NUM; j++) {
629 if (ipcTaskInfo->accessMap[j] == TRUE) {
630 (VOID)SendDeathMsg(j, i);
631 }
632 }
633 }
634 #endif
635
636 (VOID)LOS_MemFree(m_aucSysMem1, ipcTaskInfo);
637 taskCB->ipcTaskInfo = NULL;
638 }
639
SetCms(UINTPTR maxMsgSize)640 LITE_OS_SEC_TEXT STATIC UINT32 SetCms(UINTPTR maxMsgSize)
641 {
642 if (maxMsgSize < sizeof(IpcMsg)) {
643 return -EINVAL;
644 }
645 (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER);
646 #if (USE_TASKID_AS_HANDLE == 1)
647 if (g_cmsTask.status == HANDLE_NOT_USED) {
648 g_cmsTask.status = HANDLE_REGISTED;
649 g_cmsTask.taskID = LOS_CurTaskIDGet();
650 g_cmsTask.maxMsgSize = maxMsgSize;
651 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
652 return LOS_OK;
653 }
654 #else
655 if (g_serviceHandleMap[0].status == HANDLE_NOT_USED) {
656 g_serviceHandleMap[0].status = HANDLE_REGISTED;
657 g_serviceHandleMap[0].taskID = LOS_CurTaskIDGet();
658 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
659 return LOS_OK;
660 }
661 #endif
662 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
663 return -EEXIST;
664 }
665
IsCmsSet(VOID)666 LITE_OS_SEC_TEXT STATIC BOOL IsCmsSet(VOID)
667 {
668 BOOL ret;
669 (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER);
670 #if (USE_TASKID_AS_HANDLE == 1)
671 ret = g_cmsTask.status == HANDLE_REGISTED;
672 #else
673 ret = g_serviceHandleMap[0].status == HANDLE_REGISTED;
674 #endif
675 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
676 return ret;
677 }
678
IsCmsTask(UINT32 taskID)679 LITE_OS_SEC_TEXT STATIC BOOL IsCmsTask(UINT32 taskID)
680 {
681 BOOL ret;
682 (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER);
683 #if (USE_TASKID_AS_HANDLE == 1)
684 ret = IsCmsSet() ? (OS_TCB_FROM_TID(taskID)->processID == OS_TCB_FROM_TID(g_cmsTask.taskID)->processID) : FALSE;
685 #else
686 ret = IsCmsSet() ? (OS_TCB_FROM_TID(taskID)->processID ==
687 OS_TCB_FROM_TID(g_serviceHandleMap[0].taskID)->processID) : FALSE;
688 #endif
689 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
690 return ret;
691 }
692
IsTaskAlive(UINT32 taskID)693 LITE_OS_SEC_TEXT STATIC BOOL IsTaskAlive(UINT32 taskID)
694 {
695 LosTaskCB *tcb = NULL;
696 if (OS_TID_CHECK_INVALID(taskID)) {
697 return FALSE;
698 }
699 tcb = OS_TCB_FROM_TID(taskID);
700 if (!OsTaskIsUserMode(tcb)) {
701 return FALSE;
702 }
703 if (OsTaskIsUnused(tcb)) {
704 return FALSE;
705 }
706 if (OsTaskIsInactive(tcb)) {
707 return FALSE;
708 }
709 return TRUE;
710 }
711
HandleFd(UINT32 processID,SpecialObj * obj,BOOL isRollback)712 LITE_OS_SEC_TEXT STATIC UINT32 HandleFd(UINT32 processID, SpecialObj *obj, BOOL isRollback)
713 {
714 int ret;
715 if (isRollback == FALSE) {
716 ret = CopyFdToProc(obj->content.fd, processID);
717 if (ret < 0) {
718 return ret;
719 }
720 obj->content.fd = ret;
721 } else {
722 ret = CloseProcFd(obj->content.fd, processID);
723 if (ret < 0) {
724 return ret;
725 }
726 }
727
728 return LOS_OK;
729 }
730
HandlePtr(UINT32 processID,SpecialObj * obj,BOOL isRollback)731 LITE_OS_SEC_TEXT STATIC UINT32 HandlePtr(UINT32 processID, SpecialObj *obj, BOOL isRollback)
732 {
733 VOID *buf = NULL;
734 UINT32 ret;
735 if ((obj->content.ptr.buff == NULL) || (obj->content.ptr.buffSz == 0)) {
736 return -EINVAL;
737 }
738 if (isRollback == FALSE) {
739 if (LOS_IsUserAddress((vaddr_t)(UINTPTR)(obj->content.ptr.buff)) == FALSE) {
740 PRINT_ERR("Liteipc Bad ptr address\n");
741 return -EINVAL;
742 }
743 buf = LiteIpcNodeAlloc(processID, obj->content.ptr.buffSz);
744 if (buf == NULL) {
745 PRINT_ERR("Liteipc DealPtr alloc mem failed\n");
746 return -EINVAL;
747 }
748 ret = copy_from_user(buf, obj->content.ptr.buff, obj->content.ptr.buffSz);
749 if (ret != LOS_OK) {
750 LiteIpcNodeFree(processID, buf);
751 return ret;
752 }
753 obj->content.ptr.buff = (VOID *)GetIpcUserAddr(processID, (INTPTR)buf);
754 EnableIpcNodeFreeByUser(processID, (VOID *)buf);
755 } else {
756 (VOID)LiteIpcNodeFree(processID, (VOID *)GetIpcKernelAddr(processID, (INTPTR)obj->content.ptr.buff));
757 }
758 return LOS_OK;
759 }
760
HandleSvc(UINT32 dstTid,const SpecialObj * obj,BOOL isRollback)761 LITE_OS_SEC_TEXT STATIC UINT32 HandleSvc(UINT32 dstTid, const SpecialObj *obj, BOOL isRollback)
762 {
763 UINT32 taskID = 0;
764 if (isRollback == FALSE) {
765 if (IsTaskAlive(obj->content.svc.handle) == FALSE) {
766 PRINT_ERR("Liteipc HandleSvc wrong svctid\n");
767 return -EINVAL;
768 }
769 if (HasServiceAccess(obj->content.svc.handle) == FALSE) {
770 PRINT_ERR("Liteipc %s, %d\n", __FUNCTION__, __LINE__);
771 return -EACCES;
772 }
773 if (GetTid(obj->content.svc.handle, &taskID) == 0) {
774 if (taskID == OS_PCB_FROM_PID(OS_TCB_FROM_TID(taskID)->processID)->ipcInfo->ipcTaskID) {
775 AddServiceAccess(dstTid, obj->content.svc.handle);
776 }
777 }
778 }
779 return LOS_OK;
780 }
781
HandleObj(UINT32 dstTid,SpecialObj * obj,BOOL isRollback)782 LITE_OS_SEC_TEXT STATIC UINT32 HandleObj(UINT32 dstTid, SpecialObj *obj, BOOL isRollback)
783 {
784 UINT32 ret;
785 UINT32 processID = OS_TCB_FROM_TID(dstTid)->processID;
786 switch (obj->type) {
787 case OBJ_FD:
788 ret = HandleFd(processID, obj, isRollback);
789 break;
790 case OBJ_PTR:
791 ret = HandlePtr(processID, obj, isRollback);
792 break;
793 case OBJ_SVC:
794 ret = HandleSvc(dstTid, (const SpecialObj *)obj, isRollback);
795 break;
796 default:
797 ret = -EINVAL;
798 break;
799 }
800 return ret;
801 }
802
HandleSpecialObjects(UINT32 dstTid,IpcListNode * node,BOOL isRollback)803 LITE_OS_SEC_TEXT STATIC UINT32 HandleSpecialObjects(UINT32 dstTid, IpcListNode *node, BOOL isRollback)
804 {
805 UINT32 ret = LOS_OK;
806 IpcMsg *msg = &(node->msg);
807 INT32 i;
808 SpecialObj *obj = NULL;
809 UINT32 *offset = (UINT32 *)(UINTPTR)(msg->offsets);
810 if (isRollback) {
811 i = msg->spObjNum;
812 goto EXIT;
813 }
814 for (i = 0; i < msg->spObjNum; i++) {
815 if (offset[i] > msg->dataSz - sizeof(SpecialObj)) {
816 ret = -EINVAL;
817 goto EXIT;
818 }
819 if ((i > 0) && (offset[i] < offset[i - 1] + sizeof(SpecialObj))) {
820 ret = -EINVAL;
821 goto EXIT;
822 }
823 obj = (SpecialObj *)((UINTPTR)msg->data + offset[i]);
824 if (obj == NULL) {
825 ret = -EINVAL;
826 goto EXIT;
827 }
828 ret = HandleObj(dstTid, obj, FALSE);
829 if (ret != LOS_OK) {
830 goto EXIT;
831 }
832 }
833 return LOS_OK;
834 EXIT:
835 for (i--; i >= 0; i--) {
836 obj = (SpecialObj *)((UINTPTR)msg->data + offset[i]);
837 (VOID)HandleObj(dstTid, obj, TRUE);
838 }
839 return ret;
840 }
841
CheckMsgSize(IpcMsg * msg)842 LITE_OS_SEC_TEXT STATIC UINT32 CheckMsgSize(IpcMsg *msg)
843 {
844 UINT64 totalSize;
845 UINT32 i;
846 UINT32 *offset = (UINT32 *)(UINTPTR)(msg->offsets);
847 SpecialObj *obj = NULL;
848 if (msg->target.handle != 0) {
849 return LOS_OK;
850 }
851 /* msg send to cms, check the msg size */
852 totalSize = (UINT64)sizeof(IpcMsg) + msg->dataSz + msg->spObjNum * sizeof(UINT32);
853 for (i = 0; i < msg->spObjNum; i++) {
854 if (offset[i] > msg->dataSz - sizeof(SpecialObj)) {
855 return -EINVAL;
856 }
857 if ((i > 0) && (offset[i] < offset[i - 1] + sizeof(SpecialObj))) {
858 return -EINVAL;
859 }
860 obj = (SpecialObj *)((UINTPTR)msg->data + offset[i]);
861 if (obj == NULL) {
862 return -EINVAL;
863 }
864 if (obj->type == OBJ_PTR) {
865 totalSize += obj->content.ptr.buffSz;
866 }
867 }
868 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
869 if (totalSize > g_cmsTask.maxMsgSize) {
870 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
871 return -EINVAL;
872 }
873 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
874 return LOS_OK;
875 }
876
CopyDataFromUser(IpcListNode * node,UINT32 bufSz,const IpcMsg * msg)877 LITE_OS_SEC_TEXT STATIC UINT32 CopyDataFromUser(IpcListNode *node, UINT32 bufSz, const IpcMsg *msg)
878 {
879 UINT32 ret;
880 ret = (UINT32)memcpy_s((VOID *)(&node->msg), bufSz - sizeof(LOS_DL_LIST), (const VOID *)msg, sizeof(IpcMsg));
881 if (ret != LOS_OK) {
882 PRINT_DEBUG("%s, %d, %u\n", __FUNCTION__, __LINE__, ret);
883 return ret;
884 }
885
886 if (msg->dataSz) {
887 node->msg.data = (VOID *)((UINTPTR)node + sizeof(IpcListNode));
888 ret = copy_from_user((VOID *)(node->msg.data), msg->data, msg->dataSz);
889 if (ret != LOS_OK) {
890 PRINT_DEBUG("%s, %d\n", __FUNCTION__, __LINE__);
891 return ret;
892 }
893 } else {
894 node->msg.data = NULL;
895 }
896
897 if (msg->spObjNum) {
898 node->msg.offsets = (VOID *)((UINTPTR)node + sizeof(IpcListNode) + msg->dataSz);
899 ret = copy_from_user((VOID *)(node->msg.offsets), msg->offsets, msg->spObjNum * sizeof(UINT32));
900 if (ret != LOS_OK) {
901 PRINT_DEBUG("%s, %d, %x, %x, %d\n", __FUNCTION__, __LINE__, node->msg.offsets, msg->offsets, msg->spObjNum);
902 return ret;
903 }
904 } else {
905 node->msg.offsets = NULL;
906 }
907 ret = CheckMsgSize(&node->msg);
908 if (ret != LOS_OK) {
909 PRINT_DEBUG("%s, %d\n", __FUNCTION__, __LINE__);
910 return ret;
911 }
912 node->msg.taskID = LOS_CurTaskIDGet();
913 node->msg.processID = OsCurrProcessGet()->processID;
914 #ifdef LOSCFG_SECURITY_CAPABILITY
915 node->msg.userID = OsCurrProcessGet()->user->userID;
916 node->msg.gid = OsCurrProcessGet()->user->gid;
917 #endif
918 return LOS_OK;
919 }
920
IsValidReply(const IpcContent * content)921 LITE_OS_SEC_TEXT STATIC BOOL IsValidReply(const IpcContent *content)
922 {
923 UINT32 curProcessID = LOS_GetCurrProcessID();
924 IpcListNode *node = (IpcListNode *)GetIpcKernelAddr(curProcessID, (INTPTR)(content->buffToFree));
925 IpcMsg *requestMsg = &node->msg;
926 IpcMsg *replyMsg = content->outMsg;
927 UINT32 reqDstTid = 0;
928 /* Check whether the reply matches the request */
929 if ((requestMsg->type != MT_REQUEST) ||
930 (requestMsg->flag == LITEIPC_FLAG_ONEWAY) ||
931 (replyMsg->timestamp != requestMsg->timestamp) ||
932 (replyMsg->target.handle != requestMsg->taskID) ||
933 (GetTid(requestMsg->target.handle, &reqDstTid) != 0) ||
934 (OS_TCB_FROM_TID(reqDstTid)->processID != curProcessID)) {
935 return FALSE;
936 }
937 return TRUE;
938 }
939
CheckPara(IpcContent * content,UINT32 * dstTid)940 LITE_OS_SEC_TEXT STATIC UINT32 CheckPara(IpcContent *content, UINT32 *dstTid)
941 {
942 UINT32 ret;
943 IpcMsg *msg = content->outMsg;
944 UINT32 flag = content->flag;
945 #if (USE_TIMESTAMP == 1)
946 UINT64 now = LOS_CurrNanosec();
947 #endif
948 if (((msg->dataSz > 0) && (msg->data == NULL)) ||
949 ((msg->spObjNum > 0) && (msg->offsets == NULL)) ||
950 (msg->dataSz > IPC_MSG_DATA_SZ_MAX) ||
951 (msg->spObjNum > IPC_MSG_OBJECT_NUM_MAX) ||
952 (msg->dataSz < msg->spObjNum * sizeof(SpecialObj))) {
953 return -EINVAL;
954 }
955 switch (msg->type) {
956 case MT_REQUEST:
957 if (HasServiceAccess(msg->target.handle)) {
958 ret = GetTid(msg->target.handle, dstTid);
959 if (ret != LOS_OK) {
960 return -EINVAL;
961 }
962 } else {
963 PRINT_ERR("Liteipc %s, %d\n", __FUNCTION__, __LINE__);
964 return -EACCES;
965 }
966 #if (USE_TIMESTAMP == 1)
967 msg->timestamp = now;
968 #endif
969 break;
970 case MT_REPLY:
971 case MT_FAILED_REPLY:
972 if ((flag & BUFF_FREE) != BUFF_FREE) {
973 return -EINVAL;
974 }
975 if (!IsValidReply(content)) {
976 return -EINVAL;
977 }
978 #if (USE_TIMESTAMP == 1)
979 if (now > msg->timestamp + LITEIPC_TIMEOUT_NS) {
980 #ifdef LOSCFG_KERNEL_HOOK
981 ret = GetTid(msg->target.handle, dstTid);
982 if (ret != LOS_OK) {
983 *dstTid = INVAILD_ID;
984 }
985 #endif
986 OsHookCall(LOS_HOOK_TYPE_IPC_WRITE_DROP, msg, *dstTid,
987 (*dstTid == INVAILD_ID) ? INVAILD_ID : OS_TCB_FROM_TID(*dstTid)->processID, 0);
988 PRINT_ERR("Liteipc A timeout reply, request timestamp:%lld, now:%lld\n", msg->timestamp, now);
989 return -ETIME;
990 }
991 #endif
992 *dstTid = msg->target.handle;
993 break;
994 case MT_DEATH_NOTIFY:
995 *dstTid = msg->target.handle;
996 #if (USE_TIMESTAMP == 1)
997 msg->timestamp = now;
998 #endif
999 break;
1000 default:
1001 PRINT_DEBUG("Unknow msg type:%d\n", msg->type);
1002 return -EINVAL;
1003 }
1004
1005 if (IsTaskAlive(*dstTid) == FALSE) {
1006 return -EINVAL;
1007 }
1008 return LOS_OK;
1009 }
1010
LiteIpcWrite(IpcContent * content)1011 LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcWrite(IpcContent *content)
1012 {
1013 UINT32 ret, intSave;
1014 UINT32 dstTid;
1015
1016 IpcMsg *msg = content->outMsg;
1017
1018 ret = CheckPara(content, &dstTid);
1019 if (ret != LOS_OK) {
1020 return ret;
1021 }
1022
1023 LosTaskCB *tcb = OS_TCB_FROM_TID(dstTid);
1024 LosProcessCB *pcb = OS_PCB_FROM_PID(tcb->processID);
1025 if (pcb->ipcInfo == NULL) {
1026 PRINT_ERR("pid %u Liteipc not create\n", tcb->processID);
1027 return -EINVAL;
1028 }
1029
1030 UINT32 bufSz = sizeof(IpcListNode) + msg->dataSz + msg->spObjNum * sizeof(UINT32);
1031 IpcListNode *buf = (IpcListNode *)LiteIpcNodeAlloc(tcb->processID, bufSz);
1032 if (buf == NULL) {
1033 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1034 return -ENOMEM;
1035 }
1036 ret = CopyDataFromUser(buf, bufSz, (const IpcMsg *)msg);
1037 if (ret != LOS_OK) {
1038 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1039 goto ERROR_COPY;
1040 }
1041
1042 if (tcb->ipcTaskInfo == NULL) {
1043 tcb->ipcTaskInfo = LiteIpcTaskInit();
1044 }
1045
1046 ret = HandleSpecialObjects(dstTid, buf, FALSE);
1047 if (ret != LOS_OK) {
1048 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1049 goto ERROR_COPY;
1050 }
1051 /* add data to list and wake up dest task */
1052 SCHEDULER_LOCK(intSave);
1053 LOS_ListTailInsert(&(tcb->ipcTaskInfo->msgListHead), &(buf->listNode));
1054 OsHookCall(LOS_HOOK_TYPE_IPC_WRITE, &buf->msg, dstTid, tcb->processID, tcb->waitFlag);
1055 if (tcb->waitFlag == OS_TASK_WAIT_LITEIPC) {
1056 OsTaskWakeClearPendMask(tcb);
1057 OsSchedTaskWake(tcb);
1058 SCHEDULER_UNLOCK(intSave);
1059 LOS_MpSchedule(OS_MP_CPU_ALL);
1060 LOS_Schedule();
1061 } else {
1062 SCHEDULER_UNLOCK(intSave);
1063 }
1064 return LOS_OK;
1065 ERROR_COPY:
1066 LiteIpcNodeFree(OS_TCB_FROM_TID(dstTid)->processID, buf);
1067 return ret;
1068 }
1069
CheckRecievedMsg(IpcListNode * node,IpcContent * content,LosTaskCB * tcb)1070 LITE_OS_SEC_TEXT STATIC UINT32 CheckRecievedMsg(IpcListNode *node, IpcContent *content, LosTaskCB *tcb)
1071 {
1072 UINT32 ret = LOS_OK;
1073 if (node == NULL) {
1074 return -EINVAL;
1075 }
1076 switch (node->msg.type) {
1077 case MT_REQUEST:
1078 if ((content->flag & SEND) == SEND) {
1079 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1080 ret = -EINVAL;
1081 }
1082 break;
1083 case MT_FAILED_REPLY:
1084 ret = -ENOENT;
1085 /* fall-through */
1086 case MT_REPLY:
1087 if ((content->flag & SEND) != SEND) {
1088 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1089 ret = -EINVAL;
1090 }
1091 #if (USE_TIMESTAMP == 1)
1092 if (node->msg.timestamp != content->outMsg->timestamp) {
1093 PRINT_ERR("Recieve a unmatch reply, drop it\n");
1094 ret = -EINVAL;
1095 }
1096 #else
1097 if ((node->msg.code != content->outMsg->code) ||
1098 (node->msg.target.token != content->outMsg->target.token)) {
1099 PRINT_ERR("Recieve a unmatch reply, drop it\n");
1100 ret = -EINVAL;
1101 }
1102 #endif
1103 break;
1104 case MT_DEATH_NOTIFY:
1105 break;
1106 default:
1107 PRINT_ERR("Unknow msg type:%d\n", node->msg.type);
1108 ret = -EINVAL;
1109 }
1110 if (ret != LOS_OK) {
1111 OsHookCall(LOS_HOOK_TYPE_IPC_READ_DROP, &node->msg, tcb->waitFlag);
1112 (VOID)HandleSpecialObjects(LOS_CurTaskIDGet(), node, TRUE);
1113 (VOID)LiteIpcNodeFree(LOS_GetCurrProcessID(), (VOID *)node);
1114 } else {
1115 OsHookCall(LOS_HOOK_TYPE_IPC_READ, &node->msg, tcb->waitFlag);
1116 }
1117 return ret;
1118 }
1119
LiteIpcRead(IpcContent * content)1120 LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcRead(IpcContent *content)
1121 {
1122 UINT32 intSave, ret;
1123 UINT32 selfTid = LOS_CurTaskIDGet();
1124 LOS_DL_LIST *listHead = NULL;
1125 LOS_DL_LIST *listNode = NULL;
1126 IpcListNode *node = NULL;
1127 UINT32 syncFlag = (content->flag & SEND) && (content->flag & RECV);
1128 UINT32 timeout = syncFlag ? LOS_MS2Tick(LITEIPC_TIMEOUT_MS) : LOS_WAIT_FOREVER;
1129
1130 LosTaskCB *tcb = OS_TCB_FROM_TID(selfTid);
1131 if (tcb->ipcTaskInfo == NULL) {
1132 tcb->ipcTaskInfo = LiteIpcTaskInit();
1133 }
1134
1135 listHead = &(tcb->ipcTaskInfo->msgListHead);
1136 do {
1137 SCHEDULER_LOCK(intSave);
1138 if (LOS_ListEmpty(listHead)) {
1139 OsTaskWaitSetPendMask(OS_TASK_WAIT_LITEIPC, OS_INVALID_VALUE, timeout);
1140 OsHookCall(LOS_HOOK_TYPE_IPC_TRY_READ, syncFlag ? MT_REPLY : MT_REQUEST, tcb->waitFlag);
1141 ret = OsSchedTaskWait(&g_ipcPendlist, timeout, TRUE);
1142 if (ret == LOS_ERRNO_TSK_TIMEOUT) {
1143 OsHookCall(LOS_HOOK_TYPE_IPC_READ_TIMEOUT, syncFlag ? MT_REPLY : MT_REQUEST, tcb->waitFlag);
1144 SCHEDULER_UNLOCK(intSave);
1145 return -ETIME;
1146 }
1147
1148 if (OsTaskIsKilled(tcb)) {
1149 OsHookCall(LOS_HOOK_TYPE_IPC_KILL, syncFlag ? MT_REPLY : MT_REQUEST, tcb->waitFlag);
1150 SCHEDULER_UNLOCK(intSave);
1151 return -ERFKILL;
1152 }
1153
1154 SCHEDULER_UNLOCK(intSave);
1155 } else {
1156 listNode = LOS_DL_LIST_FIRST(listHead);
1157 LOS_ListDelete(listNode);
1158 node = LOS_DL_LIST_ENTRY(listNode, IpcListNode, listNode);
1159 SCHEDULER_UNLOCK(intSave);
1160 ret = CheckRecievedMsg(node, content, tcb);
1161 if (ret == LOS_OK) {
1162 break;
1163 }
1164 if (ret == -ENOENT) { /* It means that we've received a failed reply */
1165 return ret;
1166 }
1167 }
1168 } while (1);
1169 node->msg.data = (VOID *)GetIpcUserAddr(LOS_GetCurrProcessID(), (INTPTR)(node->msg.data));
1170 node->msg.offsets = (VOID *)GetIpcUserAddr(LOS_GetCurrProcessID(), (INTPTR)(node->msg.offsets));
1171 content->inMsg = (VOID *)GetIpcUserAddr(LOS_GetCurrProcessID(), (INTPTR)(&(node->msg)));
1172 EnableIpcNodeFreeByUser(LOS_GetCurrProcessID(), (VOID *)node);
1173 return LOS_OK;
1174 }
1175
LiteIpcMsgHandle(IpcContent * con)1176 LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcMsgHandle(IpcContent *con)
1177 {
1178 UINT32 ret = LOS_OK;
1179 IpcContent localContent;
1180 IpcContent *content = &localContent;
1181 IpcMsg localMsg;
1182 IpcMsg *msg = &localMsg;
1183 IpcListNode *nodeNeedFree = NULL;
1184
1185 if (copy_from_user((void *)content, (const void *)con, sizeof(IpcContent)) != LOS_OK) {
1186 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1187 return -EINVAL;
1188 }
1189
1190 if ((content->flag & BUFF_FREE) == BUFF_FREE) {
1191 ret = CheckUsedBuffer(content->buffToFree, &nodeNeedFree);
1192 if (ret != LOS_OK) {
1193 PRINT_ERR("CheckUsedBuffer failed:%d\n", ret);
1194 return ret;
1195 }
1196 }
1197
1198 if ((content->flag & SEND) == SEND) {
1199 if (content->outMsg == NULL) {
1200 PRINT_ERR("content->outmsg is null\n");
1201 ret = -EINVAL;
1202 goto BUFFER_FREE;
1203 }
1204 if (copy_from_user((void *)msg, (const void *)content->outMsg, sizeof(IpcMsg)) != LOS_OK) {
1205 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1206 ret = -EINVAL;
1207 goto BUFFER_FREE;
1208 }
1209 content->outMsg = msg;
1210 if ((content->outMsg->type < 0) || (content->outMsg->type >= MT_DEATH_NOTIFY)) {
1211 PRINT_ERR("LiteIpc unknown msg type:%d\n", content->outMsg->type);
1212 ret = -EINVAL;
1213 goto BUFFER_FREE;
1214 }
1215 ret = LiteIpcWrite(content);
1216 if (ret != LOS_OK) {
1217 PRINT_ERR("LiteIpcWrite failed\n");
1218 goto BUFFER_FREE;
1219 }
1220 }
1221 BUFFER_FREE:
1222 if (nodeNeedFree != NULL) {
1223 UINT32 freeRet = LiteIpcNodeFree(LOS_GetCurrProcessID(), nodeNeedFree);
1224 ret = (freeRet == LOS_OK) ? ret : freeRet;
1225 }
1226 if (ret != LOS_OK) {
1227 return ret;
1228 }
1229
1230 if ((content->flag & RECV) == RECV) {
1231 ret = LiteIpcRead(content);
1232 if (ret != LOS_OK) {
1233 PRINT_ERR("LiteIpcRead failed ERROR: %d\n", (INT32)ret);
1234 return ret;
1235 }
1236 UINT32 offset = LOS_OFF_SET_OF(IpcContent, inMsg);
1237 ret = copy_to_user((char*)con + offset, (char*)content + offset, sizeof(IpcMsg *));
1238 if (ret != LOS_OK) {
1239 PRINT_ERR("%s, %d, %d\n", __FUNCTION__, __LINE__, ret);
1240 return -EINVAL;
1241 }
1242 }
1243 return ret;
1244 }
1245
HandleCmsCmd(CmsCmdContent * content)1246 LITE_OS_SEC_TEXT STATIC UINT32 HandleCmsCmd(CmsCmdContent *content)
1247 {
1248 UINT32 ret = LOS_OK;
1249 CmsCmdContent localContent;
1250 if (content == NULL) {
1251 return -EINVAL;
1252 }
1253 if (IsCmsTask(LOS_CurTaskIDGet()) == FALSE) {
1254 return -EACCES;
1255 }
1256 if (copy_from_user((void *)(&localContent), (const void *)content, sizeof(CmsCmdContent)) != LOS_OK) {
1257 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1258 return -EINVAL;
1259 }
1260 switch (localContent.cmd) {
1261 case CMS_GEN_HANDLE:
1262 if ((localContent.taskID != 0) && (IsTaskAlive(localContent.taskID) == FALSE)) {
1263 return -EINVAL;
1264 }
1265 ret = GenerateServiceHandle(localContent.taskID, HANDLE_REGISTED, &(localContent.serviceHandle));
1266 if (ret == LOS_OK) {
1267 ret = copy_to_user((void *)content, (const void *)(&localContent), sizeof(CmsCmdContent));
1268 }
1269 (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER);
1270 AddServiceAccess(g_cmsTask.taskID, localContent.serviceHandle);
1271 (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux);
1272 break;
1273 case CMS_REMOVE_HANDLE:
1274 if (localContent.serviceHandle >= MAX_SERVICE_NUM) {
1275 return -EINVAL;
1276 }
1277 RefreshServiceHandle(localContent.serviceHandle, -1);
1278 break;
1279 case CMS_ADD_ACCESS:
1280 if (IsTaskAlive(localContent.taskID) == FALSE) {
1281 return -EINVAL;
1282 }
1283 return AddServiceAccess(localContent.taskID, localContent.serviceHandle);
1284 default:
1285 PRINT_DEBUG("Unknow cmd cmd:%d\n", localContent.cmd);
1286 return -EINVAL;
1287 }
1288 return ret;
1289 }
1290
LiteIpcIoctl(struct file * filep,int cmd,unsigned long arg)1291 LITE_OS_SEC_TEXT int LiteIpcIoctl(struct file *filep, int cmd, unsigned long arg)
1292 {
1293 UINT32 ret = LOS_OK;
1294 LosProcessCB *pcb = OsCurrProcessGet();
1295 ProcIpcInfo *ipcInfo = pcb->ipcInfo;
1296
1297 if (ipcInfo == NULL) {
1298 PRINT_ERR("Liteipc pool not create!\n");
1299 return -EINVAL;
1300 }
1301
1302 if (IsPoolMapped(ipcInfo) == FALSE) {
1303 PRINT_ERR("Liteipc Ipc pool not init, need to mmap first!\n");
1304 return -ENOMEM;
1305 }
1306
1307 switch (cmd) {
1308 case IPC_SET_CMS:
1309 return SetCms(arg);
1310 case IPC_CMS_CMD:
1311 return HandleCmsCmd((CmsCmdContent *)(UINTPTR)arg);
1312 case IPC_SET_IPC_THREAD:
1313 if (IsCmsSet() == FALSE) {
1314 PRINT_ERR("Liteipc ServiceManager not set!\n");
1315 return -EINVAL;
1316 }
1317 return SetIpcTask();
1318 case IPC_SEND_RECV_MSG:
1319 if (arg == 0) {
1320 return -EINVAL;
1321 }
1322 if (IsCmsSet() == FALSE) {
1323 PRINT_ERR("Liteipc ServiceManager not set!\n");
1324 return -EINVAL;
1325 }
1326 ret = LiteIpcMsgHandle((IpcContent *)(UINTPTR)arg);
1327 if (ret != LOS_OK) {
1328 return ret;
1329 }
1330 break;
1331 default:
1332 PRINT_ERR("Unknow liteipc ioctl cmd:%d\n", cmd);
1333 return -EINVAL;
1334 }
1335 return ret;
1336 }
1337