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