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 #include <cerrno>
16 #include <unistd.h>
17 #include <sys/stat.h>
18 #include "init_unittest.h"
19 #include "cJSON.h"
20 #include "sandbox.h"
21 #include "sandbox_namespace.h"
22 #include "securec.h"
23 
24 using namespace testing::ext;
25 namespace init_ut {
26 const int NULL_ROOT_PATH = 1;
27 const int NULL_MOUNT_FLAGS = 2;
28 const int NULL_MOUNT = 3;
29 const int NULL_MOUNT_ITEM = 13;
30 const int LINK_ARRARY_START = 5;
31 const int LINK_ARRARY_END = 8;
32 const int FLAGS_NUMBER = 3;
33 
34 const char *TEST_SANDBOX_NAME = "test";
35 const char *SANDBOX_JSON_NAME = "test-sandbox.json";
36 
37 const char *SANDBOX_CONFIG[] = {"sandbox-root", "mount-bind-paths", "mount-bind-files", "symbol-links"};
38 const char *SANDBOX_ROOT[] = { "/mnt/sandbox/test", "/mnt/sandbox/chipset", "/mnt/error"};
39 const char *SANDBOX_FLAGS[] = {"bind", "rec", "private"};
40 const char *MOUNT_BIND_PATHS[] = {"src-path", "sandbox-path", "sandbox-flags"};
41 const char *SYMBOL_LINKS[] = {"target-name", "link-name"};
42 const char *APP_PATHS[] = {"/mnt", "/sys", "/proc", "/dev", "/data",
43                            "/system/bin", "/system/lib", "/system/etc", "/system"};
44 
RestartSandbox(const char * sandbox)45 int RestartSandbox(const char *sandbox)
46 {
47     if (sandbox == nullptr) {
48         std::cout << "invalid parameters" << std::endl;
49         return 0;
50     }
51     InitDefaultNamespace();
52     std::cout << "init namespace" << std::endl;
53     if (!InitSandboxWithName(sandbox)) {
54         CloseDefaultNamespace();
55         std::cout << "Failed to init sandbox with name " << sandbox << std::endl;
56         return 0;
57     }
58     std::cout << "init sandbox with name" << std::endl;
59     DumpSandboxByName(sandbox);
60     std::cout << "dump sandbox" << std::endl;
61     if (PrepareSandbox(sandbox) != 0) {
62         std::cout << "Failed to prepare sandbox " << sandbox << std::endl;
63         DestroySandbox(sandbox);
64         CloseDefaultNamespace();
65         return 0;
66     }
67     std::cout << "prepare sandbox" << std::endl;
68     if (EnterDefaultNamespace() < 0) {
69         std::cout << "Failed to set default namespace" << std::endl;
70         DestroySandbox(sandbox);
71         CloseDefaultNamespace();
72         return 0;
73     }
74     std::cout << "enter default namespace" << std::endl;
75     CloseDefaultNamespace();
76     std::cout << "close namespace" << std::endl;
77     return 1;
78 }
79 
MakeSandboxJson(const char * sandboxFileName,const int MODE)80 cJSON *MakeSandboxJson(const char *sandboxFileName, const int MODE)
81 {
82     cJSON *mJsonSandbox = cJSON_CreateObject();             // json file object
83     cJSON *mJsonMtBdPth = cJSON_CreateArray();              // mount-bind-paths
84     cJSON *mJsonMtBdFl = cJSON_CreateArray();               // mount-bind-files
85     cJSON *mJsonSymLk = cJSON_CreateArray();                // symbol-links
86     cJSON *mJsonMtBdPthItmSdxFlg = cJSON_CreateArray();   // mount-bind-paths items sandbox-flags
87     cJSON *mJsonMtBdFlItm = cJSON_CreateObject();          // mount-bind-files items
88 
89     if (mJsonSandbox == nullptr || mJsonMtBdPth == nullptr || mJsonMtBdFl == nullptr ||
90         mJsonSymLk == nullptr || mJsonMtBdPthItmSdxFlg == nullptr || mJsonMtBdFlItm == nullptr) {
91         std::cout << "create json object error" << std::endl;
92         return nullptr;
93     }
94     cJSON *mJsonMtBdPth_Itm;                                // point to mount-bind-paths items
95     cJSON *mJsonSymLk_Itm;                                  // point to symbol-links items
96 
97     //  drop root path
98     if (MODE != NULL_ROOT_PATH) {
99         cJSON_AddItemToObject(mJsonSandbox, SANDBOX_CONFIG[0], cJSON_CreateString(SANDBOX_ROOT[0]));
100     }
101 
102     // assemble SANDBOX_FLAGS
103     if (MODE != NULL_MOUNT_FLAGS) {
104         for (int i = 0; i < FLAGS_NUMBER; i++) {
105             cJSON_AddItemToArray(mJsonMtBdPthItmSdxFlg, cJSON_CreateString(SANDBOX_FLAGS[i]));
106         }
107     }
108 
109     // assemble mount-bind-paths items
110     // Append items to mount-bind-paths
111     for (size_t i = 0; i < (sizeof(APP_PATHS) / sizeof(char *)); i++) {
112         cJSON_AddItemToArray(mJsonMtBdPth, mJsonMtBdPth_Itm = cJSON_CreateObject());
113         int MOUNT_FLAG_COUNT = 2;
114         if (MODE != NULL_MOUNT_ITEM) {
115             cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[0], cJSON_CreateString(APP_PATHS[i]));
116             cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[1], cJSON_CreateString(APP_PATHS[i]));
117         } else {
118             cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[0], nullptr);
119             cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[1], nullptr);
120         }
121         cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[MOUNT_FLAG_COUNT], mJsonMtBdPthItmSdxFlg);
122     }
123     if (MODE != NULL_MOUNT) {
124         cJSON_AddItemToObject(mJsonMtBdFlItm, SANDBOX_CONFIG[1], cJSON_CreateString("/data/init_ut/testsandboxfile"));
125         // Append items to mount-bind-files
126         cJSON_AddItemToArray(mJsonMtBdFl, mJsonMtBdFlItm);
127         // assemble symbol-links items
128         for (int i = LINK_ARRARY_START; i < LINK_ARRARY_END; i++) {
129             // Append items to symbol-links
130             cJSON_AddItemToArray(mJsonSymLk, mJsonSymLk_Itm = cJSON_CreateObject());
131             cJSON_AddItemToObject(mJsonSymLk_Itm, SYMBOL_LINKS[0], cJSON_CreateString(APP_PATHS[i]));
132             cJSON_AddItemToObject(mJsonSymLk_Itm, SYMBOL_LINKS[1], cJSON_CreateString(APP_PATHS[i]));
133         }
134     }
135 
136     // at last, assemble the json file
137     int count = 1;
138     cJSON_AddItemToObject(mJsonSandbox, SANDBOX_CONFIG[count++], mJsonMtBdPth);
139     cJSON_AddItemToObject(mJsonSandbox, SANDBOX_CONFIG[count++], mJsonMtBdFl);
140     cJSON_AddItemToObject(mJsonSandbox, SANDBOX_CONFIG[count], mJsonSymLk);
141     return mJsonSandbox;
142 }
143 
MakeFileByJson(cJSON * mJson,const char * sandboxFileName)144 bool MakeFileByJson(cJSON * mJson, const char *sandboxFileName)
145 {
146     const std::string  sandboxJsonPth = std::string("/data/init_ut/") + std::string(sandboxFileName);
147     const char* cSandboxJsonPth = sandboxJsonPth.c_str();
148     int fd = open(cSandboxJsonPth, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
149     if (fd < 0) {
150         std::cout << "open sandbox json file failed" << std::endl;
151         return false;
152     }
153 
154     char *cjValue1 = cJSON_Print(mJson);
155     int ret1 = write(fd, cjValue1, strlen(cjValue1));
156     if (-1 == ret1) {
157         std::cout << "Write file ERROR" << errno << "  fd is :" << fd << std::endl;
158         close(fd);
159         return false;
160     }
161     free(cjValue1);
162     close(fd);
163     return true;
164 }
165 
166 class SandboxUnitTest : public testing::Test {
167 public:
SetUpTestCase(void)168     static void SetUpTestCase(void) {}
TearDownTestCase(void)169     static void TearDownTestCase(void) {}
SetUp()170     void SetUp() {};
TearDown()171     void TearDown() {};
172 };
173 
174 HWTEST_F(SandboxUnitTest, TestCreateNormalSandbox, TestSize.Level1) {
175     cJSON *mJson = MakeSandboxJson(SANDBOX_JSON_NAME, 0);
176     if (mJson == nullptr) {
177         std::cout << "created mJson error, mJson is null." << std::endl;
178         return;
179     }
180     MakeFileByJson(mJson, SANDBOX_JSON_NAME);
181     int ret = RestartSandbox(TEST_SANDBOX_NAME);
182     ASSERT_EQ(ret, 0);
183 }
184 
185 HWTEST_F(SandboxUnitTest, TestEnterErrorSandbox, TestSize.Level1) {
186     int ret1 = EnterSandbox("error_system");
187     ASSERT_EQ(ret1, -1);
188     const char *pname = nullptr;
189     int ret2 = EnterSandbox(pname);
190     ASSERT_EQ(ret2, -1);
191     DestroySandbox(TEST_SANDBOX_NAME);
192     int ret3 = EnterSandbox(TEST_SANDBOX_NAME);
193     ASSERT_EQ(ret3, -1);
194 }
195 
196 HWTEST_F(SandboxUnitTest, TestCreateErrorSandbox1, TestSize.Level1) {
197     const char *pname = nullptr;
198     std::cout << "test destroy nullptr" << std::endl;
199     DestroySandbox(pname);
200     std::cout << "test destroy xapp" << std::endl;
201     DestroySandbox("xapp");
202     std::cout << "test enter xapp" << std::endl;
203     int ret1 = EnterSandbox("xapp");
204     ASSERT_EQ(ret1, -1);
205     bool result = InitSandboxWithName(pname);
206     ASSERT_FALSE(result);
207     DumpSandboxByName(pname);
208     DumpSandboxByName("xpp");
209     result  = InitSandboxWithName("xapp");
210     ASSERT_FALSE(result);
211 }
212 
213 HWTEST_F(SandboxUnitTest, TestCreateErrorSandbox2, TestSize.Level1) {
214     cJSON *mJson = MakeSandboxJson(SANDBOX_JSON_NAME, NULL_ROOT_PATH);
215     if (mJson == nullptr) {
216         std::cout << "created mJson error, mJson is null." << std::endl;
217         return;
218     }
219     bool ret1 = MakeFileByJson(mJson, SANDBOX_JSON_NAME);
220     ASSERT_TRUE(ret1);
221     InitSandboxWithName(TEST_SANDBOX_NAME);
222     int ret = PrepareSandbox(TEST_SANDBOX_NAME);
223     ASSERT_EQ(ret, -1);
224     ret = PrepareSandbox("xapp");
225     ASSERT_EQ(ret, -1);
226 }
227 
228 HWTEST_F(SandboxUnitTest, TestCreateSandboxNoneJsonError, TestSize.Level1) {
229     unlink("/etc/sandbox/test-sandbox.json");
230     int ret = PrepareSandbox(TEST_SANDBOX_NAME);
231     ASSERT_EQ(ret, -1);
232 }
233 
234 HWTEST_F(SandboxUnitTest, TestCreateSandboxMountFlagsError, TestSize.Level1) {
235     cJSON *mJson = MakeSandboxJson(SANDBOX_JSON_NAME, NULL_MOUNT_FLAGS);
236     if (mJson == nullptr) {
237         std::cout << "created mJson error, mJson is null." << std::endl;
238         return;
239     }
240     MakeFileByJson(mJson, SANDBOX_JSON_NAME);
241     int ret = PrepareSandbox(TEST_SANDBOX_NAME);
242     ASSERT_EQ(ret, -1);
243 }
244 
245 HWTEST_F(SandboxUnitTest, TestCreateSandboxMountNULLError, TestSize.Level1) {
246     cJSON *mJson = MakeSandboxJson(SANDBOX_JSON_NAME, NULL_MOUNT_ITEM);
247     if (mJson == nullptr) {
248         std::cout << "created mJson error, mJson is null." << std::endl;
249         return;
250     }
251     MakeFileByJson(mJson, SANDBOX_JSON_NAME);
252     int ret = PrepareSandbox(TEST_SANDBOX_NAME);
253     ASSERT_EQ(ret, -1);
254     InitSandboxWithName(TEST_SANDBOX_NAME);
255     ASSERT_EQ(ret, -1);
256 }
257 
258 HWTEST_F(SandboxUnitTest, TestUnshareNamespace, TestSize.Level1) {
259     int ret1 = UnshareNamespace(-1);
260     ASSERT_EQ(ret1, -1);
261 }
262 
263 HWTEST_F(SandboxUnitTest, TestSetNamespace, TestSize.Level1) {
264     int ret1 = SetNamespace(-1, 1);
265     ASSERT_EQ(ret1, -1);
266     ret1 = SetNamespace(1, -1);
267     ASSERT_EQ(ret1, -1);
268 }
269 
270 HWTEST_F(SandboxUnitTest, TestGetNamespaceFd, TestSize.Level1) {
271     int ret1 = GetNamespaceFd("");
272     GetNamespaceFd(nullptr);
273     ASSERT_EQ(ret1, -1);
274     const std::string  sandboxJsonPth = std::string("/mnt/sandbox/") + std::string(TEST_SANDBOX_NAME);
275     const char* cSandboxJsonPth = sandboxJsonPth.c_str();
276     ret1 = GetNamespaceFd(cSandboxJsonPth);
277     EXPECT_GT(ret1, 1);
278 }
279 }
280