1 // Copyright 2019 Google LLC
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 // https://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 <fcntl.h>
16 #include <syscall.h>
17 #include <unistd.h>
18
19 #include <cerrno>
20 #include <cstdlib>
21 #include <memory>
22 #include <string>
23 #include <utility>
24 #include <vector>
25
26 #include "absl/flags/flag.h"
27 #include "absl/flags/parse.h"
28 #include "absl/log/globals.h"
29 #include "absl/log/initialize.h"
30 #include "absl/log/check.h"
31 #include "absl/log/log.h"
32 #include "absl/base/log_severity.h"
33 #include "absl/strings/string_view.h"
34 #include "absl/time/time.h"
35 #include "sandboxed_api/sandbox2/executor.h"
36 #include "sandboxed_api/sandbox2/limits.h"
37 #include "sandboxed_api/sandbox2/policy.h"
38 #include "sandboxed_api/sandbox2/policybuilder.h"
39 #include "sandboxed_api/sandbox2/result.h"
40 #include "sandboxed_api/sandbox2/sandbox2.h"
41 #include "sandboxed_api/sandbox2/util/bpf_helper.h"
42 #include "sandboxed_api/util/runfiles.h"
43
44 ABSL_FLAG(std::string, input, "", "Input file");
45 ABSL_FLAG(std::string, output, "", "Output file");
46 ABSL_FLAG(bool, decompress, false, "Decompress instead of compress.");
47
48 namespace {
49
GetPolicy()50 std::unique_ptr<sandbox2::Policy> GetPolicy() {
51 return sandbox2::PolicyBuilder()
52 // Allow read on STDIN.
53 .AddPolicyOnSyscall(__NR_read, {ARG_32(0), JEQ32(0, ALLOW)})
54 // Allow write on STDOUT / STDERR.
55 .AddPolicyOnSyscall(__NR_write,
56 {ARG_32(0), JEQ32(1, ALLOW), JEQ32(2, ALLOW)})
57 .AllowStat()
58 .AllowStaticStartup()
59 .AllowSystemMalloc()
60 .AllowExit()
61 .BlockSyscallsWithErrno(
62 {
63 #ifdef __NR_access
64 __NR_access,
65 #endif
66 __NR_faccessat,
67 },
68 ENOENT)
69 .BuildOrDie();
70 }
71
72 } // namespace
73
main(int argc,char * argv[])74 int main(int argc, char* argv[]) {
75 absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
76 absl::ParseCommandLine(argc, argv);
77 absl::InitializeLog();
78
79 if (absl::GetFlag(FLAGS_input).empty()) {
80 LOG(ERROR) << "Parameter --input required.";
81 return 1;
82 }
83
84 if (absl::GetFlag(FLAGS_output).empty()) {
85 LOG(ERROR) << "Parameter --output required.";
86 return 1;
87 }
88
89 // Note: In your own code, use sapi::GetDataDependencyFilePath() instead.
90 const std::string path = sapi::internal::GetSapiDataDependencyFilePath(
91 "sandbox2/examples/zlib/zpipe");
92 std::vector<std::string> args = {path};
93 if (absl::GetFlag(FLAGS_decompress)) {
94 args.push_back("-d");
95 }
96 std::vector<std::string> envs = {};
97 auto executor = std::make_unique<sandbox2::Executor>(path, args, envs);
98
99 executor
100 // Kill sandboxed processes with a signal (SIGXFSZ) if it writes more than
101 // these many bytes to the file-system.
102 ->limits()
103 ->set_rlimit_fsize(1ULL << 30) // 1GiB
104 .set_rlimit_cpu(60) // The CPU time limit in seconds.
105 .set_walltime_limit(absl::Seconds(5));
106
107 // Create input + output FD.
108 int fd_in = open(absl::GetFlag(FLAGS_input).c_str(), O_RDONLY);
109 int fd_out = open(absl::GetFlag(FLAGS_output).c_str(),
110 O_WRONLY | O_CREAT | O_TRUNC, 0644);
111 CHECK_GE(fd_in, 0);
112 CHECK_GE(fd_out, 0);
113 executor->ipc()->MapFd(fd_in, STDIN_FILENO);
114 executor->ipc()->MapFd(fd_out, STDOUT_FILENO);
115
116 auto policy = GetPolicy();
117 sandbox2::Sandbox2 s2(std::move(executor), std::move(policy));
118
119 // Let the sandboxee run.
120 auto result = s2.Run();
121 close(fd_in);
122 close(fd_out);
123 if (result.final_status() != sandbox2::Result::OK) {
124 LOG(ERROR) << "Sandbox error: " << result.ToString();
125 return 2; // e.g. sandbox violation, signal (sigsegv)
126 }
127 auto code = result.reason_code();
128 if (code) {
129 LOG(ERROR) << "Sandboxee exited with non-zero: " << code;
130 return 3; // e.g. normal child error
131 }
132 LOG(INFO) << "Sandboxee finished: " << result.ToString();
133 return EXIT_SUCCESS;
134 }
135