1 /*
2  * Copyright (c) 2024 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 "appspawn_adapter.h"
17 
18 #include <sys/signalfd.h>
19 #include <sys/wait.h>
20 #include "securec.h"
21 
22 #include "appspawn_hook.h"
23 #include "appspawn_utils.h"
24 #include "init_utils.h"
25 
SetSystemEnv(void)26 APPSPAWN_STATIC void SetSystemEnv(void)
27 {
28     int32_t ret;
29     char envValue[MAX_ENV_VALUE_LEN];
30     ret = ConvertEnvValue("/bin:/system/bin:${PATH}", envValue, MAX_ENV_VALUE_LEN);
31     APPSPAWN_CHECK(ret == 0, return, "Convert env value failed");
32     ret = setenv("PATH", envValue, true);
33     APPSPAWN_CHECK(ret == 0, return, "Set env fail value=%{public}s", envValue);
34 }
35 
RunAppSandbox(const char * ptyName)36 APPSPAWN_STATIC void RunAppSandbox(const char *ptyName)
37 {
38     if (ptyName == NULL) {
39         return;
40     }
41 #ifndef APPSPAWN_TEST
42     SetSystemEnv();
43     OpenConsole();
44     char *realPath = realpath(ptyName, NULL);
45     if (realPath == NULL) {
46         APPSPAWN_CHECK(errno == ENOENT, return,
47             "Failed to resolve %{public}s real path err=%{public}d", ptyName, errno);
48     }
49     APPSPAWN_CHECK(realPath != NULL, _exit(1), "Failed get realpath, err=%{public}d", errno);
50     int n = strncmp(realPath, "/dev/pts/", strlen("/dev/pts/"));
51     APPSPAWN_CHECK(n == 0, free(realPath); _exit(1), "pts path %{public}s is invaild", realPath);
52     int fd = open(realPath, O_RDWR);
53     free(realPath);
54     APPSPAWN_CHECK(fd >= 0, _exit(1), "Failed open %{public}s, err=%{public}d", ptyName, errno);
55     (void)dup2(fd, STDIN_FILENO);
56     (void)dup2(fd, STDOUT_FILENO);
57     (void)dup2(fd, STDERR_FILENO); // Redirect fd to 0, 1, 2
58     (void)close(fd);
59 
60     char *argv[] = { (char *)"/bin/sh", NULL };
61     APPSPAWN_CHECK_ONLY_LOG(execv(argv[0], argv) == 0,
62         "app %{public}s execv sh failed! err %{public}d.", ptyName, errno);
63     _exit(0x7f); // 0x7f: user specified
64 #endif
65     APPSPAWN_LOGE("Exit RunAppSandbox %{public}s exit", ptyName);
66 }
67 
RunBegetctlBootApp(AppSpawnMgr * content,AppSpawningCtx * property)68 APPSPAWN_STATIC int RunBegetctlBootApp(AppSpawnMgr *content, AppSpawningCtx *property)
69 {
70     APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1);
71     UNUSED(content);
72     if ((property->client.flags & APP_BEGETCTL_BOOT) != APP_BEGETCTL_BOOT) {
73         APPSPAWN_LOGW("Enter begetctl boot without BEGETCTL_BOOT flag set");
74         return 0;
75     }
76     uint32_t len = 0;
77     const char *cmdMsg = (const char *)GetAppSpawnMsgExtInfo(property->message, MSG_EXT_NAME_BEGET_PTY_NAME, &len);
78     APPSPAWN_CHECK(cmdMsg != NULL, return -1, "Failed to get extInfo");
79     RunAppSandbox(cmdMsg);
80     return 0;
81 }
82 
MODULE_CONSTRUCTOR(void)83 MODULE_CONSTRUCTOR(void)
84 {
85     AddAppSpawnHook(STAGE_CHILD_PRE_RUN, HOOK_PRIO_LOWEST, RunBegetctlBootApp);
86 }
87 
88