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