1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cerrno>
17 #include <cstdlib>
18 #include <cstdio>
19 #include <cstdint>
20 #include <getopt.h>
21 #include <iostream>
22 #include <map>
23 #include <securec.h>
24 #include <string>
25 #include <unistd.h>
26 #include <vector>
27 
28 #ifdef ENABLE_ENTER_APPSPAWN_SANDBOX
29 #include "appspawn.h"
30 #endif
31 #include "begetctl.h"
32 #include "control_fd.h"
33 #include "init_utils.h"
34 #include "sandbox.h"
35 #include "sandbox_namespace.h"
36 #include "string_ex.h"
37 
38 using namespace OHOS;
39 struct option g_options[] = {
40     { "service_name", required_argument, nullptr, 's' },
41     { "namespace_name", required_argument, nullptr, 'n' },
42     { "process_name", required_argument, nullptr, 'p' },
43     { "process_pid", required_argument, nullptr, 'b' },
44     { "help", no_argument, nullptr, 'h' },
45     { nullptr, 0, nullptr, 0 },
46 };
47 
Usage()48 static void Usage()
49 {
50     std::cout << "sandbox -s | -n [-p] | -p | -b | -h" << std::endl;
51     std::cout << "sandbox -s, --service_name=sandbox service \"enter service sandbox\"" << std::endl;
52     std::cout << "sandbox -n, --namespace_name=namespace name \"namespace name, system, chipset etc.\"" << std::endl;
53     std::cout << "sandbox -p, --process=process name \"sh, hdcd, hdf_devhost, etc.\"" << std::endl;
54     std::cout << "sandbox -b, --process_pid=process pid \"sh, enter native app sandbox, etc.\"" << std::endl;
55     std::cout << "sandbox -h, --help \"Show help\"" << std::endl;
56 #ifndef STARTUP_INIT_TEST
57     exit(0);
58 #endif
59 }
60 
RunSandbox(const std::string & sandboxName)61 static void RunSandbox(const std::string &sandboxName)
62 {
63     InitDefaultNamespace();
64     if (!InitSandboxWithName(sandboxName.c_str())) {
65         std::cout << "Init sandbox failed." << std::endl;
66         return;
67     }
68 
69     DumpSandboxByName(sandboxName.c_str());
70     if (PrepareSandbox(sandboxName.c_str()) != 0) {
71         std::cout << "Prepare sandbox failed." << std::endl;
72         return;
73     }
74     EnterDefaultNamespace();
75     CloseDefaultNamespace();
76     EnterSandbox(sandboxName.c_str());
77     return;
78 }
79 
EnterShell()80 static void EnterShell()
81 {
82     char *argv[] = { const_cast<char *>("sh"), nullptr };
83     char *envp[] = { nullptr };
84     if (execve("/system/bin/sh", argv, envp) != 0) {
85         std::cout << "execve sh failed! err = "<< errno << std::endl;
86     }
87     return;
88 }
89 
90 static const int MAX_PROCESS_ARGC = 8;
EnterExec(const std::string & processName)91 static void EnterExec(const std::string &processName)
92 {
93     std::string tmpName = processName;
94     std::vector<std::string> vtr;
95     const std::string sep = " ";
96     OHOS::SplitStr(tmpName, sep, vtr, true, false);
97 
98     if ((vtr.size() > MAX_PROCESS_ARGC) || (vtr.size() == 0)) {
99         std::cout << "Service parameters is error." << std::endl;
100         return;
101     }
102     char *argv[MAX_PROCESS_ARGC] = {};
103     std::vector<std::string>::iterator it;
104     int i = 0;
105     for (it = vtr.begin(); it != vtr.end(); ++it) {
106         argv[i] = (char *)(*it).c_str();
107         std::cout << std::string(argv[i]) << std::endl;
108         i++;
109     }
110     argv[i] = NULL;
111     char *envp[] = { NULL };
112     if (execve(argv[0], argv, envp) != 0) {
113         std::cout << "execve:" << argv[0] << "failed! err = "<< errno << std::endl;
114     }
115     return;
116 }
117 
SendAppspawnCmdMessage(const CmdAgent * agent,uint16_t type,const char * cmd,const char * ptyName)118 static int SendAppspawnCmdMessage(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName)
119 {
120 #ifdef ENABLE_ENTER_APPSPAWN_SANDBOX
121     if ((agent == NULL) || (cmd == NULL) || (ptyName == NULL)) {
122         BEGET_LOGE("Invalid parameter");
123         return -1;
124     }
125 
126     AppSpawnClientHandle clientHandle;
127     int ret = AppSpawnClientInit("AppSpawn", &clientHandle);
128     BEGET_ERROR_CHECK(ret == 0,  return -1, "AppSpawnClientInit error, errno = %d", errno);
129     AppSpawnReqMsgHandle reqHandle;
130     ret = AppSpawnReqMsgCreate(AppSpawnMsgType::MSG_BEGET_CMD, cmd, &reqHandle);
131     BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle); return -1, "AppSpawnReqMsgCreate error");
132     ret = AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_BEGETCTL_BOOT);
133     BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle); return -1, "AppSpawnReqMsgSetAppFlag error");
134     ret = AppSpawnReqMsgAddStringInfo(reqHandle, MSG_EXT_NAME_BEGET_PID, cmd);
135     BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle); return -1, "add %s request message error", cmd);
136     ret = AppSpawnReqMsgAddStringInfo(reqHandle, MSG_EXT_NAME_BEGET_PTY_NAME, ptyName);
137     BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle);
138         return -1, "add %s request message error", ptyName);
139     AppSpawnResult result = {};
140     ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
141     if (ret != 0 || result.result != 0) {
142         AppSpawnClientDestroy(clientHandle);
143         return -1;
144     }
145     AppSpawnClientDestroy(clientHandle);
146     return 0;
147 #endif
148     return -1;
149 }
150 
CmdAppspawnClientInit(const char * cmd,CallbackSendMsgProcess sendMsg)151 static void CmdAppspawnClientInit(const char *cmd, CallbackSendMsgProcess sendMsg)
152 {
153     if (cmd == nullptr) {
154         BEGET_LOGE("[control_fd] Invalid parameter");
155         return;
156     }
157 
158     CmdAgent agent;
159     int ret = InitPtyInterface(&agent, ACTION_APP_SANDBOX, cmd, sendMsg);
160     if (ret != 0) {
161         BEGET_LOGE("App with pid=%s does not support entering sandbox environment", cmd);
162         return;
163     }
164     LE_RunLoop(LE_GetDefaultLoop());
165     LE_CloseLoop(LE_GetDefaultLoop());
166     BEGET_LOGI("Cmd Client exit ");
167 }
168 
RunCmd(const std::string & serviceName,const std::string & namespaceName,const std::string & processName,const std::string & pid)169 static void RunCmd(const std::string &serviceName, const std::string &namespaceName, const std::string &processName,
170     const std::string &pid)
171 {
172     bool isNamespaceOnly = !namespaceName.empty() && processName.empty() && serviceName.empty() && pid.empty();
173     bool isNamespaceAndProcess = !namespaceName.empty() && !processName.empty() && serviceName.empty() && pid.empty();
174     bool isProcessOnly = namespaceName.empty() && !processName.empty() && serviceName.empty() && pid.empty();
175     bool isServiceOnly = namespaceName.empty() && processName.empty() && !serviceName.empty() && pid.empty();
176     bool isPidOnly = namespaceName.empty() && processName.empty() && serviceName.empty() && !pid.empty();
177     if (isNamespaceOnly) {
178         RunSandbox(namespaceName);
179         EnterShell();
180     } else if (isNamespaceAndProcess) {
181         RunSandbox(namespaceName);
182         EnterExec(processName);
183     } else if (isProcessOnly) {
184         std::cout << "process name:" << processName << std::endl;
185         RunSandbox(std::string("system"));
186         EnterExec(processName);
187     } else if (isServiceOnly) {
188         std::cout << "enter sandbox service name " << serviceName << std::endl;
189         CmdClientInit(INIT_CONTROL_FD_SOCKET_PATH, ACTION_SANDBOX, serviceName.c_str(), nullptr);
190     } else if (isPidOnly) {
191         CmdAppspawnClientInit(pid.c_str(), SendAppspawnCmdMessage);
192     } else {
193         Usage();
194     }
195 }
196 
main_cmd(BShellHandle shell,int argc,char ** argv)197 static int main_cmd(BShellHandle shell, int argc, char **argv)
198 {
199     int rc = -1;
200     int optIndex = -1;
201     std::string serviceName {};
202     std::string namespaceName {};
203     std::string processName {};
204     std::string pid {};
205     while ((rc = getopt_long(argc, argv, "s:n:p:h:b:",  g_options, &optIndex)) != -1) {
206         switch (rc) {
207             case 0: {
208                 std::string optionName = g_options[optIndex].name;
209                 if (optionName == "service_name") {
210                     serviceName = optarg;
211                 } else if (optionName == "help") {
212                     Usage();
213                 } else if (optionName == "namespace_name") {
214                     namespaceName = optarg;
215                 } else if (optionName == "process_name") {
216                     processName = optarg;
217                 } else if (optionName == "process_pid") {
218                     pid = optarg;
219                 }
220                 break;
221             }
222             case 's':
223                 serviceName = optarg;
224                 break;
225             case 'h':
226                 Usage();
227                 break;
228             case 'n':
229                 namespaceName = optarg;
230                 break;
231             case 'p':
232                 processName = optarg;
233                 break;
234             case 'b':
235                 pid = optarg;
236                 break;
237             case '?':
238                 std::cout << "Invalid argument\n";
239                 break;
240             default:
241                 std::cout << "Invalid argument\n";
242                 break;
243         }
244     }
245     RunCmd(serviceName, namespaceName, processName, pid);
246     return 0;
247 }
248 
MODULE_CONSTRUCTOR(void)249 MODULE_CONSTRUCTOR(void)
250 {
251     const CmdInfo infos[] = {
252         {
253             const_cast<char *>("sandbox"), main_cmd, const_cast<char *>("enter service sandbox"),
254             const_cast<char *>("sandbox -s service_name"),
255             NULL
256         },
257         {
258             const_cast<char *>("sandbox"), main_cmd, const_cast<char *>("enter namespace, system, chipset etc."),
259             const_cast<char *>("sandbox -n namespace_name [-p]"),
260             NULL
261         },
262         {
263             const_cast<char *>("sandbox"), main_cmd, const_cast<char *>("enter namespace and exec process"),
264             const_cast<char *>("sandbox -p process_name"),
265             NULL
266         },
267         {
268             const_cast<char *>("sandbox"), main_cmd, const_cast<char *>("enter native app sandbox namespace"),
269             const_cast<char *>("sandbox -b pid"),
270             NULL
271         }
272     };
273     for (size_t i = 0; i < ARRAY_LENGTH(infos); i++) {
274         BShellEnvRegisterCmd(GetShellHandle(), &infos[i]);
275     }
276 }
277