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
94 if (LOS_IsUserAddress((VADDR_T)(UINTPTR)fileName)) {
95 err = LOS_StrncpyFromUser(kfileName, fileName, PATH_MAX + 1);
96 if (err == -EFAULT) {
97 return err;
98 } else if (err > PATH_MAX) {
99 PRINT_ERR("%s[%d], filename len exceeds maxlen: %d\n", __FUNCTION__, __LINE__, PATH_MAX);
100 return -ENAMETOOLONG;
101 }
102 } else if (LOS_IsKernelAddress((VADDR_T)(UINTPTR)fileName)) {
103 strLen = strlen(fileName);
104 err = memcpy_s(kfileName, PATH_MAX, fileName, strLen);
105 if (err != EOK) {
106 PRINT_ERR("%s[%d], Copy failed! err: %d\n", __FUNCTION__, __LINE__, err);
107 return -EFAULT;
108 }
109 } else {
110 return -EINVAL;
111 }
112
113 loadInfo->fileName = kfileName;
114 return LOS_OK;
115 }
116
LOS_DoExecveFile(const CHAR * fileName,CHAR * const * argv,CHAR * const * envp)117 INT32 LOS_DoExecveFile(const CHAR *fileName, CHAR * const *argv, CHAR * const *envp)
118 {
119 ELFLoadInfo loadInfo = { 0 };
120 CHAR kfileName[PATH_MAX + 1] = { 0 };
121 INT32 ret;
122 #ifdef LOSCFG_SHELL
123 CHAR buf[PATH_MAX + 1] = { 0 };
124 #endif
125
126 if ((fileName == NULL) || ((argv != NULL) && !LOS_IsUserAddress((VADDR_T)(UINTPTR)argv)) ||
127 ((envp != NULL) && !LOS_IsUserAddress((VADDR_T)(UINTPTR)envp))) {
128 return -EINVAL;
129 }
130 ret = OsCopyUserParam(&loadInfo, fileName, kfileName, PATH_MAX);
131 if (ret != LOS_OK) {
132 return ret;
133 }
134
135 #ifdef LOSCFG_SHELL
136 if (OsGetRealPath(kfileName, buf, (PATH_MAX + 1)) != LOS_OK) {
137 return -ENOENT;
138 }
139 if (buf[0] != '\0') {
140 loadInfo.fileName = buf;
141 }
142 #endif
143
144 loadInfo.newSpace = OsCreateUserVmSpace();
145 if (loadInfo.newSpace == NULL) {
146 PRINT_ERR("%s %d, failed to allocate new vm space\n", __FUNCTION__, __LINE__);
147 return -ENOMEM;
148 }
149
150 loadInfo.argv = argv;
151 loadInfo.envp = envp;
152
153 ret = OsLoadELFFile(&loadInfo);
154 if (ret != LOS_OK) {
155 return ret;
156 }
157
158 ret = OsExecRecycleAndInit(OsCurrProcessGet(), loadInfo.fileName, loadInfo.oldSpace, loadInfo.oldFiles);
159 if (ret != LOS_OK) {
160 (VOID)LOS_VmSpaceFree(loadInfo.oldSpace);
161 goto OUT;
162 }
163
164 ret = OsExecve(&loadInfo);
165 if (ret != LOS_OK) {
166 goto OUT;
167 }
168
169 return loadInfo.stackTop;
170
171 OUT:
172 (VOID)LOS_Exit(OS_PRO_EXIT_OK);
173 return ret;
174 }
175