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