// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sandboxed_api/util/flag.h" #include "absl/memory/memory.h" #include "sandboxed_api/sandbox2/comms.h" #include "sandboxed_api/sandbox2/executor.h" #include "sandboxed_api/sandbox2/limits.h" #include "sandboxed_api/sandbox2/policy.h" #include "sandboxed_api/sandbox2/policybuilder.h" #include "sandboxed_api/sandbox2/result.h" #include "sandboxed_api/sandbox2/sandbox2.h" #include "sandboxed_api/sandbox2/util/bpf_helper.h" #include "sandboxed_api/util/runfiles.h" using std::string; ABSL_FLAG(string, input, "", "Input file"); ABSL_FLAG(string, output, "", "Output file"); ABSL_FLAG(bool, decompress, false, "Decompress instead of compress."); namespace { std::unique_ptr GetPolicy() { return sandbox2::PolicyBuilder() // Allow read on STDIN. .AddPolicyOnSyscall(__NR_read, {ARG_32(0), JEQ32(0, ALLOW)}) // Allow write on STDOUT / STDERR. .AddPolicyOnSyscall(__NR_write, {ARG_32(0), JEQ32(1, ALLOW), JEQ32(2, ALLOW)}) .AllowSyscall(__NR_fstat) .AllowStaticStartup() .AllowSystemMalloc() .AllowExit() #ifdef __NR_access .BlockSyscallWithErrno(__NR_access, ENOENT) #endif #ifdef __NR_faccessat .BlockSyscallWithErrno(__NR_faccessat, ENOENT) #endif .BuildOrDie(); } } // namespace int main(int argc, char** argv) { gflags::ParseCommandLineFlags(&argc, &argv, true); google::InitGoogleLogging(argv[0]); if (absl::GetFlag(FLAGS_input).empty()) { LOG(ERROR) << "Parameter --input required."; return 1; } if (absl::GetFlag(FLAGS_output).empty()) { LOG(ERROR) << "Parameter --output required."; return 1; } // Note: In your own code, use sapi::GetDataDependencyFilePath() instead. const std::string path = sapi::internal::GetSapiDataDependencyFilePath( "sandbox2/examples/zlib/zpipe"); std::vector args = {path}; if (absl::GetFlag(FLAGS_decompress)) { args.push_back("-d"); } std::vector envs = {}; auto executor = absl::make_unique(path, args, envs); executor // Kill sandboxed processes with a signal (SIGXFSZ) if it writes more than // these many bytes to the file-system. ->limits() ->set_rlimit_fsize(1ULL << 30) // 1GiB .set_rlimit_cpu(60) // The CPU time limit in seconds. .set_walltime_limit(absl::Seconds(5)); // Create input + output FD. int fd_in = open(absl::GetFlag(FLAGS_input).c_str(), O_RDONLY); int fd_out = open(absl::GetFlag(FLAGS_output).c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644); CHECK_GE(fd_in, 0); CHECK_GE(fd_out, 0); executor->ipc()->MapFd(fd_in, STDIN_FILENO); executor->ipc()->MapFd(fd_out, STDOUT_FILENO); auto policy = GetPolicy(); sandbox2::Sandbox2 s2(std::move(executor), std::move(policy)); // Let the sandboxee run. auto result = s2.Run(); close(fd_in); close(fd_out); if (result.final_status() != sandbox2::Result::OK) { LOG(ERROR) << "Sandbox error: " << result.ToString(); return 2; // e.g. sandbox violation, signal (sigsegv) } auto code = result.reason_code(); if (code) { LOG(ERROR) << "Sandboxee exited with non-zero: " << code; return 3; // e.g. normal child error } LOG(INFO) << "Sandboxee finished: " << result.ToString(); return EXIT_SUCCESS; }