• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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