• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gtest/gtest.h>
17 
18 #include <gtest/gtest.h>
19 
20 #include <cstdlib>
21 #include <unistd.h>
22 #include <sys/wait.h>
23 #include <csignal>
24 #include <cerrno>
25 #include <cstring>
26 #include <sys/prctl.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <sys/syscall.h>
31 #include <asm/unistd.h>
32 #include <syscall.h>
33 #include <climits>
34 
35 #include "seccomp_policy.h"
36 
37 using SyscallFunc = bool (*)(void);
38 constexpr int SLEEP_TIME = 100000; // 100ms
39 
40 using namespace testing::ext;
41 using namespace std;
42 
43 namespace init_ut {
44 class SeccompUnitTest : public testing::Test {
45 public:
SeccompUnitTest()46     SeccompUnitTest() {};
~SeccompUnitTest()47     virtual ~SeccompUnitTest() {};
SetUpTestCase()48     static void SetUpTestCase() {};
TearDownTestCase()49     static void TearDownTestCase() {};
SetUp()50     void SetUp() {};
TearDown()51     void TearDown() {};
TestBody(void)52     void TestBody(void) {};
Handler(int s)53     static void Handler(int s)
54     {
55     }
56 
StartChild(const char * filterName,SyscallFunc func)57     static pid_t StartChild(const char *filterName, SyscallFunc func)
58     {
59         pid_t pid = fork();
60         if (pid == 0) {
61             if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) {
62                 std::cout << "PR_SET_NO_NEW_PRIVS set fail " << std::endl;
63                 exit(EXIT_FAILURE);
64             }
65             if (!SetSeccompPolicyWithName(filterName)) {
66                 std::cout << "SetSeccompPolicy set fail fiterName is " << filterName << std::endl;
67                 exit(EXIT_FAILURE);
68             }
69 
70             if (!func()) {
71                 std::cout << "func excute fail" << std::endl;
72                 exit(EXIT_FAILURE);
73             }
74 
75             std::cout << "func excute success" << std::endl;
76 
77             exit(EXIT_SUCCESS);
78         }
79         return pid;
80     }
81 
CheckSyscall(const char * filterName,SyscallFunc func,bool isAllow)82     static int CheckSyscall(const char *filterName, SyscallFunc func, bool isAllow)
83     {
84         sigset_t set;
85         int status;
86         pid_t pid;
87         int flag = 0;
88         struct timespec waitTime = {5, 0};
89 
90         sigemptyset(&set);
91         sigaddset(&set, SIGCHLD);
92         sigprocmask(SIG_BLOCK, &set, nullptr);
93         if (signal(SIGCHLD, Handler) == nullptr) {
94             std::cout << "signal failed:" << strerror(errno) << std::endl;
95         }
96 
97         /* Sleeping for avoiding influencing child proccess wait for other threads
98          * which were created by other unittests to release global rwlock. The global
99          * rwlock will be used by function dlopen in child process */
100         usleep(SLEEP_TIME);
101 
102         pid = StartChild(filterName, func);
103         if (pid == -1) {
104             std::cout << "fork failed:" << strerror(errno) << std::endl;
105             return -1;
106         }
107         if (sigtimedwait(&set, nullptr, &waitTime) == -1) { /* Wait for 5 seconds */
108             if (errno == EAGAIN) {
109                 flag = 1;
110             } else {
111                 std::cout << "sigtimedwait failed:" << strerror(errno) << std::endl;
112             }
113 
114             if (kill(pid, SIGKILL) == -1) {
115                 std::cout << "kill failed::" << strerror(errno) << std::endl;
116             }
117         }
118 
119         if (waitpid(pid, &status, 0) != pid) {
120             std::cout << "waitpid failed:" << strerror(errno) << std::endl;
121             return -1;
122         }
123 
124         if (flag != 0) {
125             std::cout << "Child process time out" << std::endl;
126         }
127 
128         if (WEXITSTATUS(status) == EXIT_FAILURE) {
129             return -1;
130         }
131 
132         if (WIFSIGNALED(status)) {
133             if (WTERMSIG(status) == SIGSYS) {
134                     std::cout << "child process exit with SIGSYS" << std::endl;
135                     return isAllow ? -1 : 0;
136             }
137         } else {
138             std::cout << "child process finished normally" << std::endl;
139             return isAllow ? 0 : -1;
140         }
141         return -1;
142     }
143 
144 #if defined __aarch64__
CheckGetMempolicy()145     static bool CheckGetMempolicy()
146     {
147         int ret = syscall(__NR_get_mempolicy, NULL, NULL, 0, NULL, 0);
148         if (ret < 0) {
149             return false;
150         }
151 
152         return true;
153     }
154 
CheckGetpid()155     static bool CheckGetpid()
156     {
157         pid_t pid = 1;
158         pid = syscall(__NR_getpid);
159         if (pid > 1) {
160             return true;
161         }
162         return false;
163     }
164 
CheckGetuid()165     static bool CheckGetuid()
166     {
167         uid_t uid = 0;
168         uid = syscall(__NR_getuid);
169         if (uid >= 0) {
170             return true;
171         }
172 
173         return false;
174     }
175 
CheckSetresuidArgsInRange()176     static bool CheckSetresuidArgsInRange()
177     {
178         int ret = syscall(__NR_setresuid, 20000, 20000, 20000);
179         if (ret == 0) {
180             return true;
181         }
182 
183         return false;
184     }
185 
CheckSetresuidArgsOutOfRange()186     static bool CheckSetresuidArgsOutOfRange()
187     {
188         int ret = syscall(__NR_setresuid, 800, 800, 800);
189         if (ret == 0) {
190             return true;
191         }
192 
193         return false;
194     }
195 
CheckSetuid()196     static bool CheckSetuid()
197     {
198         int uid = syscall(__NR_setuid, 1);
199         if (uid == 0) {
200             return true;
201         }
202 
203         return false;
204     }
205 
TestSystemSycall()206     void TestSystemSycall()
207     {
208         // system blocklist
209         int ret = CheckSyscall(SYSTEM_NAME, CheckGetMempolicy, false);
210         EXPECT_EQ(ret, 0);
211 
212         // system allowlist
213         ret = CheckSyscall(SYSTEM_NAME, CheckGetpid, true);
214         EXPECT_EQ(ret, 0);
215     }
216 
TestSetUidGidFilter()217     void TestSetUidGidFilter()
218     {
219         // system blocklist
220         int ret = CheckSyscall(APPSPAWN_NAME, CheckSetresuidArgsOutOfRange, false);
221         EXPECT_EQ(ret, 0);
222 
223         // system allowlist
224         ret = CheckSyscall(APPSPAWN_NAME, CheckSetresuidArgsInRange, true);
225         EXPECT_EQ(ret, 0);
226     }
227 
TestAppSycall()228     void TestAppSycall()
229     {
230         // app blocklist
231         int ret = CheckSyscall(APP_NAME, CheckSetuid, false);
232         EXPECT_EQ(ret, 0);
233 
234         // app allowlist
235         ret = CheckSyscall(APP_NAME, CheckGetpid, true);
236         EXPECT_EQ(ret, 0);
237     }
238 #elif defined __arm__
CheckGetuid32()239     static bool CheckGetuid32()
240     {
241         uid_t uid = syscall(__NR_getuid32);
242         if (uid >= 0) {
243             return true;
244         }
245         return false;
246     }
247 
CheckGetuid()248     static bool CheckGetuid()
249     {
250         uid_t uid = syscall(__NR_getuid);
251         if (uid >= 0) {
252             return true;
253         }
254         return false;
255     }
256 
CheckSetuid32()257     static bool CheckSetuid32()
258     {
259         int ret = syscall(__NR_setuid32, 1);
260         if (ret == 0) {
261             return true;
262         }
263 
264         return false;
265     }
266 
CheckSetresuid32ArgsInRange()267     static bool CheckSetresuid32ArgsInRange()
268     {
269         int ret = syscall(__NR_setresuid32, 20000, 20000, 20000);
270         if (ret == 0) {
271             return true;
272         }
273 
274         return false;
275     }
276 
CheckSetresuid32ArgsOutOfRange()277     static bool CheckSetresuid32ArgsOutOfRange()
278     {
279         int ret = syscall(__NR_setresuid32, 800, 800, 800);
280         if (ret == 0) {
281             return true;
282         }
283 
284         return false;
285     }
286 
TestSystemSycall()287     void TestSystemSycall()
288     {
289         // system blocklist
290         int ret = CheckSyscall(SYSTEM_NAME, CheckGetuid, false);
291         EXPECT_EQ(ret, 0);
292 
293         // system allowlist
294         ret = CheckSyscall(SYSTEM_NAME, CheckGetuid32, true);
295         EXPECT_EQ(ret, 0);
296     }
297 
TestSetUidGidFilter()298     void TestSetUidGidFilter()
299     {
300         // system blocklist
301         int ret = CheckSyscall(APPSPAWN_NAME, CheckSetresuid32ArgsOutOfRange, false);
302         EXPECT_EQ(ret, 0);
303 
304         // system allowlist
305         ret = CheckSyscall(APPSPAWN_NAME, CheckSetresuid32ArgsInRange, true);
306         EXPECT_EQ(ret, 0);
307     }
308 
TestAppSycall()309     void TestAppSycall()
310     {
311         // app blocklist
312         int ret = CheckSyscall(APP_NAME, CheckSetuid32, false);
313         EXPECT_EQ(ret, 0);
314 
315         // app allowlist
316         ret = CheckSyscall(APP_NAME, CheckGetuid32, true);
317         EXPECT_EQ(ret, 0);
318     }
319 #endif
320 };
321 
322 /**
323  * @tc.name: TestSystemSycall
324  * @tc.desc: Verify the system seccomp policy.
325  * @tc.type: FUNC
326  * @tc.require: issueI5IUWJ
327  */
328 HWTEST_F(SeccompUnitTest, TestSystemSycall, TestSize.Level1)
329 {
330     SeccompUnitTest test;
331     test.TestSystemSycall();
332 }
333 
334 /**
335  * @tc.name: TestSetUidGidFilter
336  * @tc.desc: Verify the system seccomp policy.
337  * @tc.type: FUNC
338  * @tc.require: issueI5IUWJ
339  */
340 HWTEST_F(SeccompUnitTest, TestSetUidGidFilter, TestSize.Level1)
341 {
342     SeccompUnitTest test;
343     test.TestSetUidGidFilter();
344 }
345 
346 /**
347  * @tc.name: TestSystemSycall
348  * @tc.desc: Verify the system seccomp policy.
349  * @tc.type: FUNC
350  * @tc.require: issueI5MUXD
351  */
352 HWTEST_F(SeccompUnitTest, TestAppSycall, TestSize.Level1)
353 {
354     SeccompUnitTest test;
355     test.TestAppSycall();
356 }
357 }
358