• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_exec_elf.h"
33 #ifdef LOSCFG_SHELL
34 #include "show.h"
35 #endif
36 #include "los_vm_phys.h"
37 #include "los_vm_map.h"
38 #include "los_vm_dump.h"
39 
OsExecve(const ELFLoadInfo * loadInfo)40 STATIC INT32 OsExecve(const ELFLoadInfo *loadInfo)
41 {
42     if ((loadInfo == NULL) || (loadInfo->elfEntry == 0)) {
43         return LOS_NOK;
44     }
45 
46     return OsExecStart((TSK_ENTRY_FUNC)(loadInfo->elfEntry), (UINTPTR)loadInfo->stackTop,
47                        loadInfo->stackBase, loadInfo->stackSize);
48 }
49 
50 #ifdef LOSCFG_SHELL
OsGetRealPath(const CHAR * fileName,CHAR * buf,UINT32 maxLen)51 STATIC INT32 OsGetRealPath(const CHAR *fileName, CHAR *buf, UINT32 maxLen)
52 {
53     CHAR *workingDirectory = NULL;
54     UINT32 len, workPathLen, newLen;
55 
56     if (access(fileName, F_OK) < 0) {
57         workingDirectory = OsShellGetWorkingDirectory();
58         if (workingDirectory == NULL) {
59             goto ERR_FILE;
60         }
61         len = strlen(fileName);
62         workPathLen = strlen(workingDirectory);
63         newLen = len + 1 + workPathLen + 1;
64         if (newLen >= maxLen) {
65             return -ENOENT;
66         }
67         if (strncpy_s(buf, maxLen, workingDirectory, workPathLen) != EOK) {
68             PRINT_ERR("strncpy_s failed, errline: %d!\n", __LINE__);
69             return -ENOENT;
70         }
71         buf[workPathLen] = '/';
72         if (strncpy_s(buf + workPathLen + 1, maxLen - workPathLen - 1, fileName, len) != EOK) {
73             PRINT_ERR("strncpy_s failed, errline: %d!\n", __LINE__);
74             return -ENOENT;
75         }
76         buf[newLen] = '\0';
77         if (access(buf, F_OK) < 0) {
78             goto ERR_FILE;
79         }
80     }
81 
82     return LOS_OK;
83 
84 ERR_FILE:
85     return -ENOENT;
86 }
87 #endif
88 
OsCopyUserParam(ELFLoadInfo * loadInfo,const CHAR * fileName,CHAR * kfileName,UINT32 maxSize)89 STATIC INT32 OsCopyUserParam(ELFLoadInfo *loadInfo, const CHAR *fileName, CHAR *kfileName, UINT32 maxSize)
90 {
91     UINT32 strLen;
92     errno_t err;
93     static UINT32 userFirstInitFlag = 0;
94 
95     if (LOS_IsUserAddress((VADDR_T)(UINTPTR)fileName)) {
96         err = LOS_StrncpyFromUser(kfileName, fileName, PATH_MAX + 1);
97         if (err == -EFAULT) {
98             return err;
99         } else if (err > PATH_MAX) {
100             PRINT_ERR("%s[%d], filename len exceeds maxlen: %d\n", __FUNCTION__, __LINE__, PATH_MAX);
101             return -ENAMETOOLONG;
102         }
103     } else if (LOS_IsKernelAddress((VADDR_T)(UINTPTR)fileName) && (userFirstInitFlag == 0)) {
104         /**
105          * the first user process is created by the function OsUserInit->execve(/bin/init) in the kernel space
106          * after the first user process is created, this branch should not enter again
107          */
108         userFirstInitFlag = 1;
109         strLen = strlen(fileName);
110         err = memcpy_s(kfileName, PATH_MAX, fileName, strLen);
111         if (err != EOK) {
112             PRINT_ERR("%s[%d], Copy failed! err: %d\n", __FUNCTION__, __LINE__, err);
113             return -EFAULT;
114         }
115     } else {
116         return -EINVAL;
117     }
118 
119     loadInfo->fileName = kfileName;
120     return LOS_OK;
121 }
122 
LOS_DoExecveFile(const CHAR * fileName,CHAR * const * argv,CHAR * const * envp)123 INT32 LOS_DoExecveFile(const CHAR *fileName, CHAR * const *argv, CHAR * const *envp)
124 {
125     ELFLoadInfo loadInfo = { 0 };
126     CHAR kfileName[PATH_MAX + 1] = { 0 };
127     INT32 ret;
128 #ifdef LOSCFG_SHELL
129     CHAR buf[PATH_MAX + 1] = { 0 };
130 #endif
131 
132     if ((fileName == NULL) || ((argv != NULL) && !LOS_IsUserAddress((VADDR_T)(UINTPTR)argv)) ||
133         ((envp != NULL) && !LOS_IsUserAddress((VADDR_T)(UINTPTR)envp))) {
134         return -EINVAL;
135     }
136     ret = OsCopyUserParam(&loadInfo, fileName, kfileName, PATH_MAX);
137     if (ret != LOS_OK) {
138         return ret;
139     }
140 
141 #ifdef LOSCFG_SHELL
142     if (OsGetRealPath(kfileName, buf, (PATH_MAX + 1)) != LOS_OK) {
143         return -ENOENT;
144     }
145     if (buf[0] != '\0') {
146         loadInfo.fileName = buf;
147     }
148 #endif
149 
150     loadInfo.newSpace = OsCreateUserVmSpace();
151     if (loadInfo.newSpace == NULL) {
152         PRINT_ERR("%s %d, failed to allocate new vm space\n", __FUNCTION__, __LINE__);
153         return -ENOMEM;
154     }
155 
156     loadInfo.argv = argv;
157     loadInfo.envp = envp;
158 
159     ret = OsLoadELFFile(&loadInfo);
160     if (ret != LOS_OK) {
161         return ret;
162     }
163 
164     ret = OsExecRecycleAndInit(OsCurrProcessGet(), loadInfo.fileName, loadInfo.oldSpace, loadInfo.oldFiles);
165     if (ret != LOS_OK) {
166         (VOID)LOS_VmSpaceFree(loadInfo.oldSpace);
167         goto OUT;
168     }
169 
170     ret = OsExecve(&loadInfo);
171     if (ret != LOS_OK) {
172         goto OUT;
173     }
174 
175     return loadInfo.stackTop;
176 
177 OUT:
178     (VOID)LOS_Exit(OS_PRO_EXIT_OK);
179     return ret;
180 }
181