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