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