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