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 38using namespace OHOS; 39struct 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 48static 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 61static 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 80static 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 90static const int MAX_PROCESS_ARGC = 8; 91static 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 118static 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 151static 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 169static 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 197static 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 249MODULE_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