gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/seccomp.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 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 <errno.h> 16 #include <linux/audit.h> 17 #include <linux/filter.h> 18 #include <linux/seccomp.h> 19 #include <pthread.h> 20 #include <sched.h> 21 #include <signal.h> 22 #include <string.h> 23 #include <sys/prctl.h> 24 #include <sys/syscall.h> 25 #include <time.h> 26 #include <ucontext.h> 27 #include <unistd.h> 28 29 #include <atomic> 30 31 #include "gmock/gmock.h" 32 #include "gtest/gtest.h" 33 #include "absl/base/macros.h" 34 #include "test/util/logging.h" 35 #include "test/util/memory_util.h" 36 #include "test/util/multiprocess_util.h" 37 #include "test/util/platform_util.h" 38 #include "test/util/posix_error.h" 39 #include "test/util/proc_util.h" 40 #include "test/util/test_util.h" 41 #include "test/util/thread_util.h" 42 43 #ifndef SYS_SECCOMP 44 #define SYS_SECCOMP 1 45 #endif 46 47 namespace gvisor { 48 namespace testing { 49 50 namespace { 51 52 // A syscall not implemented by Linux that we don't expect to be called. 53 #ifdef __x86_64__ 54 constexpr uint32_t kFilteredSyscall = SYS_vserver; 55 #elif __aarch64__ 56 // Use the last of arch_specific_syscalls which are not implemented on arm64. 57 constexpr uint32_t kFilteredSyscall = __NR_arch_specific_syscall + 15; 58 #endif 59 60 // Applies a seccomp-bpf filter that returns `filtered_result` for 61 // `sysno` and allows all other syscalls. Async-signal-safe. 62 void ApplySeccompFilter(uint32_t sysno, uint32_t filtered_result, 63 uint32_t flags = 0) { 64 // "Prior to [PR_SET_SECCOMP], the task must call prctl(PR_SET_NO_NEW_PRIVS, 65 // 1) or run with CAP_SYS_ADMIN privileges in its namespace." - 66 // Documentation/prctl/seccomp_filter.txt 67 // 68 // prctl(PR_SET_NO_NEW_PRIVS, 1) may be called repeatedly; calls after the 69 // first are no-ops. 70 TEST_PCHECK(prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0); 71 MaybeSave(); 72 73 struct sock_filter filter[] = { 74 // A = seccomp_data.arch 75 BPF_STMT(BPF_LD | BPF_ABS | BPF_W, 4), 76 #if defined(__x86_64__) 77 // if (A != AUDIT_ARCH_X86_64) goto kill 78 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 0, 4), 79 #elif defined(__aarch64__) 80 // if (A != AUDIT_ARCH_AARCH64) goto kill 81 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_AARCH64, 0, 4), 82 #else 83 #error "Unknown architecture" 84 #endif 85 // A = seccomp_data.nr 86 BPF_STMT(BPF_LD | BPF_ABS | BPF_W, 0), 87 // if (A != sysno) goto allow 88 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, sysno, 0, 1), 89 // return filtered_result 90 BPF_STMT(BPF_RET | BPF_K, filtered_result), 91 // allow: return SECCOMP_RET_ALLOW 92 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), 93 // kill: return SECCOMP_RET_KILL 94 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL), 95 }; 96 struct sock_fprog prog; 97 prog.len = ABSL_ARRAYSIZE(filter); 98 prog.filter = filter; 99 if (flags) { 100 TEST_CHECK(syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, flags, &prog) == 101 0); 102 } else { 103 TEST_PCHECK(prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0) == 0); 104 } 105 MaybeSave(); 106 } 107 108 // ApplyUncacheableFilter adds a no-op filter which reads one of the 109 // syscall arguments when queried about `sysno`, and returns ALLOW. 110 // This purposefully breaks the Linux seccomp cache. 111 void ApplyUncacheableFilter(uint32_t sysno) { 112 // "Prior to [PR_SET_SECCOMP], the task must call prctl(PR_SET_NO_NEW_PRIVS, 113 // 1) or run with CAP_SYS_ADMIN privileges in its namespace." - 114 // Documentation/prctl/seccomp_filter.txt 115 // 116 // prctl(PR_SET_NO_NEW_PRIVS, 1) may be called repeatedly; calls after the 117 // first are no-ops. 118 TEST_PCHECK(prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0); 119 MaybeSave(); 120 121 struct sock_filter filter[] = { 122 // A = seccomp_data.arch 123 BPF_STMT(BPF_LD | BPF_ABS | BPF_W, 4), 124 #if defined(__x86_64__) 125 // if (A != AUDIT_ARCH_X86_64) goto kill 126 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 0, 4), 127 #elif defined(__aarch64__) 128 // if (A != AUDIT_ARCH_AARCH64) goto kill 129 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_AARCH64, 0, 4), 130 #else 131 #error "Unknown architecture" 132 #endif 133 // A = seccomp_data.nr 134 BPF_STMT(BPF_LD | BPF_ABS | BPF_W, 0), 135 // if (A != sysno) goto end 136 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, sysno, 0, 1), 137 // A = seccomp_data.args[0] 138 BPF_STMT(BPF_LD | BPF_ABS | BPF_W, 16), 139 // end: return SECCOMP_RET_ALLOW 140 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), 141 // kill: return SECCOMP_RET_KILL 142 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL), 143 }; 144 struct sock_fprog prog; 145 prog.len = ABSL_ARRAYSIZE(filter); 146 prog.filter = filter; 147 TEST_PCHECK(prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0) == 0); 148 MaybeSave(); 149 } 150 151 // Wrapper for sigaction. Async-signal-safe. 152 void RegisterSignalHandler(int signum, 153 void (*handler)(int, siginfo_t*, void*)) { 154 struct sigaction sa = {}; 155 sa.sa_sigaction = handler; 156 sigemptyset(&sa.sa_mask); 157 sa.sa_flags = SA_SIGINFO; 158 TEST_PCHECK(sigaction(signum, &sa, nullptr) == 0); 159 MaybeSave(); 160 } 161 162 // All of the following tests execute in a subprocess to ensure that each test 163 // is run in a separate process. This avoids cross-contamination of seccomp 164 // state between tests, and is necessary to ensure that test processes killed 165 // by SECCOMP_RET_KILL are single-threaded (since SECCOMP_RET_KILL only kills 166 // the offending thread, not the whole thread group). 167 168 TEST(SeccompTest, RetKillCausesDeathBySIGSYS) { 169 pid_t const pid = fork(); 170 if (pid == 0) { 171 // Register a signal handler for SIGSYS that we don't expect to be invoked. 172 RegisterSignalHandler(SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); }); 173 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_KILL); 174 syscall(kFilteredSyscall); 175 TEST_CHECK_MSG(false, "Survived invocation of test syscall"); 176 } 177 ASSERT_THAT(pid, SyscallSucceeds()); 178 int status; 179 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 180 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGSYS) 181 << "status " << status; 182 } 183 184 TEST(SeccompTest, RetKillOnlyKillsOneThread) { 185 Mapping stack = ASSERT_NO_ERRNO_AND_VALUE( 186 MmapAnon(2 * kPageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE)); 187 188 pid_t const pid = fork(); 189 if (pid == 0) { 190 // Register a signal handler for SIGSYS that we don't expect to be invoked. 191 RegisterSignalHandler(SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); }); 192 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_KILL); 193 // Pass CLONE_VFORK to block the original thread in the child process until 194 // the clone thread exits with SIGSYS. 195 // 196 // N.B. clone(2) is not officially async-signal-safe, but at minimum glibc's 197 // x86_64 implementation is safe. See glibc 198 // sysdeps/unix/sysv/linux/x86_64/clone.S. 199 clone( 200 +[](void* arg) { 201 syscall(kFilteredSyscall); // should kill the thread 202 _exit(1); // should be unreachable 203 return 2; // should be very unreachable, shut up the compiler 204 }, 205 stack.endptr(), 206 CLONE_FILES | CLONE_FS | CLONE_SIGHAND | CLONE_THREAD | CLONE_VM | 207 CLONE_VFORK, 208 nullptr); 209 _exit(0); 210 } 211 ASSERT_THAT(pid, SyscallSucceeds()); 212 int status; 213 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 214 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 215 << "status " << status; 216 } 217 218 TEST(SeccompTest, RetTrapCausesSIGSYS) { 219 pid_t const pid = fork(); 220 if (pid == 0) { 221 constexpr uint16_t kTrapValue = 0xdead; 222 RegisterSignalHandler( 223 SIGSYS, +[](int signo, siginfo_t* info, void* ucv) { 224 ucontext_t* uc = static_cast<ucontext_t*>(ucv); 225 // This is a signal handler, so we must stay async-signal-safe. 226 TEST_CHECK(info->si_signo == SIGSYS); 227 TEST_CHECK(info->si_code == SYS_SECCOMP); 228 TEST_CHECK(info->si_errno == kTrapValue); 229 TEST_CHECK(info->si_call_addr != nullptr); 230 TEST_CHECK(info->si_syscall == kFilteredSyscall); 231 #if defined(__x86_64__) 232 TEST_CHECK(info->si_arch == AUDIT_ARCH_X86_64); 233 TEST_CHECK(uc->uc_mcontext.gregs[REG_RAX] == kFilteredSyscall); 234 #elif defined(__aarch64__) 235 TEST_CHECK(info->si_arch == AUDIT_ARCH_AARCH64); 236 TEST_CHECK(uc->uc_mcontext.regs[8] == kFilteredSyscall); 237 #endif // defined(__x86_64__) 238 _exit(0); 239 }); 240 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_TRAP | kTrapValue); 241 syscall(kFilteredSyscall); 242 TEST_CHECK_MSG(false, "Survived invocation of test syscall"); 243 } 244 ASSERT_THAT(pid, SyscallSucceeds()); 245 int status; 246 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 247 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 248 << "status " << status; 249 } 250 251 #ifdef __x86_64__ 252 253 constexpr uint64_t kVsyscallTimeEntry = 0xffffffffff600400; 254 255 time_t vsyscall_time(time_t* t) { 256 return reinterpret_cast<time_t (*)(time_t*)>(kVsyscallTimeEntry)(t); 257 } 258 259 TEST(SeccompTest, SeccompAppliesToVsyscall) { 260 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(IsVsyscallEnabled())); 261 SKIP_IF(PlatformSupportVsyscall() == PlatformSupport::NotSupported); 262 263 pid_t const pid = fork(); 264 if (pid == 0) { 265 constexpr uint16_t kTrapValue = 0xdead; 266 RegisterSignalHandler( 267 SIGSYS, +[](int signo, siginfo_t* info, void* ucv) { 268 ucontext_t* uc = static_cast<ucontext_t*>(ucv); 269 // This is a signal handler, so we must stay async-signal-safe. 270 TEST_CHECK(info->si_signo == SIGSYS); 271 TEST_CHECK(info->si_code == SYS_SECCOMP); 272 TEST_CHECK(info->si_errno == kTrapValue); 273 TEST_CHECK(info->si_call_addr != nullptr); 274 TEST_CHECK(info->si_syscall == SYS_time); 275 TEST_CHECK(info->si_arch == AUDIT_ARCH_X86_64); 276 TEST_CHECK(uc->uc_mcontext.gregs[REG_RAX] == SYS_time); 277 _exit(0); 278 }); 279 ApplySeccompFilter(SYS_time, SECCOMP_RET_TRAP | kTrapValue); 280 vsyscall_time(nullptr); // Should result in death. 281 TEST_CHECK_MSG(false, "Survived invocation of test syscall"); 282 } 283 ASSERT_THAT(pid, SyscallSucceeds()); 284 int status; 285 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 286 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 287 << "status " << status; 288 } 289 290 TEST(SeccompTest, RetKillVsyscallCausesDeathBySIGSYS) { 291 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(IsVsyscallEnabled())); 292 SKIP_IF(PlatformSupportVsyscall() == PlatformSupport::NotSupported); 293 294 pid_t const pid = fork(); 295 if (pid == 0) { 296 // Register a signal handler for SIGSYS that we don't expect to be invoked. 297 RegisterSignalHandler(SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); }); 298 ApplySeccompFilter(SYS_time, SECCOMP_RET_KILL); 299 vsyscall_time(nullptr); // Should result in death. 300 TEST_CHECK_MSG(false, "Survived invocation of test syscall"); 301 } 302 ASSERT_THAT(pid, SyscallSucceeds()); 303 int status; 304 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 305 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGSYS) 306 << "status " << status; 307 } 308 309 #endif // defined(__x86_64__) 310 311 TEST(SeccompTest, RetTraceWithoutPtracerReturnsENOSYS) { 312 pid_t const pid = fork(); 313 if (pid == 0) { 314 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_TRACE); 315 TEST_CHECK(syscall(kFilteredSyscall) == -1 && errno == ENOSYS); 316 _exit(0); 317 } 318 ASSERT_THAT(pid, SyscallSucceeds()); 319 int status; 320 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 321 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 322 << "status " << status; 323 } 324 325 TEST(SeccompTest, RetErrnoReturnsErrno) { 326 pid_t const pid = fork(); 327 if (pid == 0) { 328 // ENOTNAM: "Not a XENIX named type file" 329 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_ERRNO | ENOTNAM); 330 TEST_CHECK(syscall(kFilteredSyscall) == -1 && errno == ENOTNAM); 331 _exit(0); 332 } 333 ASSERT_THAT(pid, SyscallSucceeds()); 334 int status; 335 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 336 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 337 << "status " << status; 338 } 339 340 TEST(SeccompTest, RetAllowAllowsSyscall) { 341 pid_t const pid = fork(); 342 if (pid == 0) { 343 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_ALLOW); 344 TEST_CHECK(syscall(kFilteredSyscall) == -1 && errno == ENOSYS); 345 _exit(0); 346 } 347 ASSERT_THAT(pid, SyscallSucceeds()); 348 int status; 349 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 350 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 351 << "status " << status; 352 } 353 354 TEST(SeccompTest, RetAllowAllowsNonCachableSyscall) { 355 pid_t const pid = fork(); 356 if (pid == 0) { 357 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_ALLOW); 358 ApplyUncacheableFilter(kFilteredSyscall); 359 TEST_CHECK(syscall(kFilteredSyscall) == -1 && errno == ENOSYS); 360 _exit(0); 361 } 362 ASSERT_THAT(pid, SyscallSucceeds()); 363 int status; 364 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 365 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 366 << "status " << status; 367 } 368 369 // This test will validate that TSYNC will apply to all threads. 370 TEST(SeccompTest, TsyncAppliesToAllThreads) { 371 Mapping stack = ASSERT_NO_ERRNO_AND_VALUE( 372 MmapAnon(2 * kPageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE)); 373 374 // We don't want to apply this policy to other test runner threads, so fork. 375 const pid_t pid = fork(); 376 377 if (pid == 0) { 378 // First check that we receive a ENOSYS before the policy is applied. 379 TEST_CHECK(syscall(kFilteredSyscall) == -1 && errno == ENOSYS); 380 381 // N.B. clone(2) is not officially async-signal-safe, but at minimum glibc's 382 // x86_64 implementation is safe. See glibc 383 // sysdeps/unix/sysv/linux/x86_64/clone.S. 384 clone( 385 +[](void* arg) { 386 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_ERRNO | ENOTNAM, 387 SECCOMP_FILTER_FLAG_TSYNC); 388 return 0; 389 }, 390 stack.endptr(), 391 CLONE_FILES | CLONE_FS | CLONE_SIGHAND | CLONE_THREAD | CLONE_VM | 392 CLONE_VFORK, 393 nullptr); 394 395 // Because we're using CLONE_VFORK this thread will be blocked until 396 // the second thread has released resources to our virtual memory, since 397 // we're not execing that will happen on _exit. 398 399 // Now verify that the policy applied to this thread too. 400 TEST_CHECK(syscall(kFilteredSyscall) == -1 && errno == ENOTNAM); 401 _exit(0); 402 } 403 404 ASSERT_THAT(pid, SyscallSucceeds()); 405 int status = 0; 406 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 407 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 408 << "status " << status; 409 } 410 411 // This test will validate that seccomp(2) rejects unsupported flags. 412 TEST(SeccompTest, SeccompRejectsUnknownFlags) { 413 constexpr uint32_t kInvalidFlag = 123; 414 ASSERT_THAT( 415 syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, kInvalidFlag, nullptr), 416 SyscallFailsWithErrno(EINVAL)); 417 } 418 419 TEST(SeccompTest, LeastPermissiveFilterReturnValueApplies) { 420 // This is RetKillCausesDeathBySIGSYS, plus extra filters before and after the 421 // one that causes the kill that should be ignored. 422 pid_t const pid = fork(); 423 if (pid == 0) { 424 RegisterSignalHandler(SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); }); 425 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_TRACE); 426 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_KILL); 427 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_ERRNO | ENOTNAM); 428 syscall(kFilteredSyscall); 429 TEST_CHECK_MSG(false, "Survived invocation of test syscall"); 430 } 431 ASSERT_THAT(pid, SyscallSucceeds()); 432 int status; 433 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 434 EXPECT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGSYS) 435 << "status " << status; 436 } 437 438 // Passed as argv[1] to cause the test binary to invoke kFilteredSyscall and 439 // exit. Not a real flag since flag parsing happens during initialization, 440 // which may create threads. 441 constexpr char kInvokeFilteredSyscallFlag[] = "--seccomp_test_child"; 442 443 TEST(SeccompTest, FiltersPreservedAcrossForkAndExecve) { 444 ExecveArray const grandchild_argv( 445 {"/proc/self/exe", kInvokeFilteredSyscallFlag}); 446 447 pid_t const pid = fork(); 448 if (pid == 0) { 449 ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_KILL); 450 pid_t const grandchild_pid = fork(); 451 if (grandchild_pid == 0) { 452 execve(grandchild_argv.get()[0], grandchild_argv.get(), 453 /* envp = */ nullptr); 454 TEST_PCHECK_MSG(false, "execve failed"); 455 } 456 int status; 457 TEST_PCHECK(waitpid(grandchild_pid, &status, 0) == grandchild_pid); 458 TEST_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGSYS); 459 _exit(0); 460 } 461 ASSERT_THAT(pid, SyscallSucceeds()); 462 int status; 463 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 464 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) 465 << "status " << status; 466 } 467 468 TEST(SeccompTest, EmptyProgramIsRejected) { 469 struct sock_fprog prog; 470 prog.len = 0; 471 prog.filter = nullptr; 472 ASSERT_THAT(syscall(__NR_seccomp, SECCOMP_MODE_FILTER, &prog), 473 SyscallFailsWithErrno(EINVAL)); 474 MaybeSave(); 475 ASSERT_THAT(prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0), 476 SyscallFailsWithErrno(EINVAL)); 477 } 478 479 TEST(SeccompTest, ProgramTooLargeIsRejected) { 480 constexpr int kTooLargeFilterSize = 4097; // BPF_MAXINSNS + 1 481 TEST_PCHECK(prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0); 482 MaybeSave(); 483 struct sock_filter filter[kTooLargeFilterSize]; 484 for (int i = 0; i < kTooLargeFilterSize; ++i) { 485 filter[i] = BPF_STMT(BPF_LD | BPF_ABS | BPF_W, 0); // A = seccomp_data.nr 486 } 487 filter[kTooLargeFilterSize - 1] = 488 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW); // Return allow 489 struct sock_fprog prog; 490 prog.len = ABSL_ARRAYSIZE(filter); 491 prog.filter = filter; 492 ASSERT_THAT(syscall(__NR_seccomp, SECCOMP_MODE_FILTER, &prog), 493 SyscallFailsWithErrno(EINVAL)); 494 MaybeSave(); 495 ASSERT_THAT(prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0), 496 SyscallFailsWithErrno(EINVAL)); 497 } 498 499 } // namespace 500 501 } // namespace testing 502 } // namespace gvisor 503 504 int main(int argc, char** argv) { 505 if (argc >= 2 && 506 strcmp(argv[1], gvisor::testing::kInvokeFilteredSyscallFlag) == 0) { 507 syscall(gvisor::testing::kFilteredSyscall); 508 exit(0); 509 } 510 511 gvisor::testing::TestInit(&argc, &argv); 512 return gvisor::testing::RunAllTests(); 513 }