2727#include < initializer_list>
2828#include < memory>
2929#include < string>
30- #include < utility>
31- #include < variant>
32- #include < vector>
3330
34- #include " sandboxed_api/file_toc.h"
3531#include " absl/base/dynamic_annotations.h"
3632#include " absl/base/macros.h"
3733#include " absl/log/check.h"
4137#include " absl/strings/str_cat.h"
4238#include " absl/strings/str_format.h"
4339#include " absl/strings/string_view.h"
44- #include " absl/synchronization/mutex.h"
4540#include " absl/time/time.h"
4641#include " absl/types/span.h"
4742#include " sandboxed_api/call.h"
4843#include " sandboxed_api/config.h"
49- #include " sandboxed_api/embed_file.h"
5044#include " sandboxed_api/rpcchannel.h"
51- #include " sandboxed_api/sandbox2/executor.h"
52- #include " sandboxed_api/sandbox2/fork_client.h"
5345#include " sandboxed_api/sandbox2/limits.h"
5446#include " sandboxed_api/sandbox2/policy.h"
5547#include " sandboxed_api/sandbox2/policybuilder.h"
56- #include " sandboxed_api/sandbox2/result.h"
57- #include " sandboxed_api/sandbox2/sandbox2.h"
58- #include " sandboxed_api/sandbox2_rpcchannel.h"
59- #include " sandboxed_api/util/path.h"
60- #include " sandboxed_api/util/runfiles.h"
6148#include " sandboxed_api/util/status_macros.h"
6249#include " sandboxed_api/var_abstract.h"
6350#include " sandboxed_api/var_array.h"
6855
6956namespace sapi {
7057
71- Sandbox::Sandbox (SandboxConfig config) : config_(std::move(config)) {
72- CHECK (config_.sandbox2 .fork_client_context .has_value ());
73- }
74-
75- Sandbox::~Sandbox () {
76- Terminate ();
77- // The forkserver will die automatically when the executor goes out of scope
78- // and closes the comms object.
79- }
80-
8158// IMPORTANT: This policy must be safe to use with
8259// `Allow(sandbox2::UnrestrictedNetworking())`.
8360sandbox2::PolicyBuilder Sandbox2Config::DefaultPolicyBuilder () {
@@ -132,198 +109,21 @@ sandbox2::Limits Sandbox2Config::DefaultLimits() {
132109 return limits;
133110}
134111
135- void Sandbox::Terminate (bool attempt_graceful_exit) {
136- if (!is_active ()) {
137- return ;
138- }
139-
140- absl::StatusOr<sandbox2::Result> result;
141- if (attempt_graceful_exit) {
142- if (absl::Status requested_exit = rpc_channel_->Exit ();
143- !requested_exit.ok ()) {
144- LOG (WARNING )
145- << " rpc_channel->Exit() failed, calling AwaitResultWithTimeout(1) "
146- << requested_exit;
147- }
148- result = s2_->AwaitResultWithTimeout (absl::Seconds (1 ));
149- if (!result.ok ()) {
150- LOG (WARNING ) << " s2_->AwaitResultWithTimeout failed, status: "
151- << result.status () << " Killing PID: " << pid ();
152- }
153- }
154-
155- if (!attempt_graceful_exit || !result.ok ()) {
156- s2_->Kill ();
157- result = s2_->AwaitResult ();
158- }
159-
160- if ((result->final_status () == sandbox2::Result::OK &&
161- result->reason_code () == 0 ) ||
162- (!attempt_graceful_exit &&
163- result->final_status () == sandbox2::Result::EXTERNAL_KILL )) {
164- VLOG (2 ) << " Sandbox2 finished with: " << result->ToString ();
165- } else {
166- LOG (WARNING ) << " Sandbox2 finished with: " << result->ToString ();
167- }
168- }
169-
170- static std::string PathToSAPILib (const std::string& lib_path) {
171- return file::IsAbsolutePath (lib_path) ? lib_path
172- : GetDataDependencyFilePath (lib_path);
173- }
174-
175- void Sandbox::ApplySandbox2Config (sandbox2::Executor* executor) const {
176- const Sandbox2Config& config = config_.sandbox2 ;
177- if (config.enable_log_server ) {
178- executor->ipc ()->EnableLogServer ();
179- }
180- if (config.cwd .has_value ()) {
181- executor->set_cwd (*config.cwd );
182- }
183- if (config.limits .has_value ()) {
184- *executor->limits () = *config.limits ;
185- }
186- }
187-
188- void Sandbox::MapFileDescriptors (sandbox2::Executor* executor) const {
189- if (!config_.fd_mappings .has_value ()) {
190- return ;
191- }
192- for (const auto & [host_fd, sandbox_fd] : *config_.fd_mappings ) {
193- executor->ipc ()->MapDupedFd (host_fd.get (), sandbox_fd);
194- }
195- }
196-
197- absl::Status Sandbox::Init () {
198- // It's already initialized
199- if (is_active ()) {
200- return absl::OkStatus ();
201- }
202-
203- std::shared_ptr<sandbox2::Executor> fork_client_executor;
204- std::shared_ptr<sandbox2::ForkClient> fork_client;
205- {
206- absl::MutexLock lock (fork_client_shared ().mu_ );
207- // Initialize the forkserver if it is not already running.
208- if (!fork_client_shared ().client_ ) {
209- auto sandboxee_source = fork_client_context ().sandboxee_source_ ;
210-
211- std::string lib_path;
212- int embed_lib_fd = -1 ;
213- if (std::holds_alternative<const FileToc*>(sandboxee_source)) {
214- const FileToc* embed_lib_toc =
215- std::get<const FileToc*>(sandboxee_source);
216- embed_lib_fd = EmbedFile::instance ()->GetDupFdForFileToc (embed_lib_toc);
217- if (embed_lib_fd == -1 ) {
218- PLOG (ERROR ) << " Cannot create executable FD for TOC:'"
219- << embed_lib_toc->name << " '" ;
220- return absl::UnavailableError (" Could not create executable FD" );
221- }
222- lib_path = embed_lib_toc->name ;
223- } else {
224- lib_path = PathToSAPILib (std::get<std::string>(sandboxee_source));
225- if (lib_path.empty ()) {
226- LOG (ERROR ) << " SAPI library path is empty" ;
227- return absl::FailedPreconditionError (" No SAPI library path given" );
228- }
229- }
230- std::vector<std::string> args = {lib_path};
231- // Additional arguments, if needed.
232- auto flags =
233- config_.command_line_flags .value_or (SandboxConfig::DefaultFlags ());
234- for (const auto & [key, value] : flags) {
235- args.push_back (absl::StrCat (" --" , key, " =" , value));
236- }
237-
238- fork_client_shared ().executor_ =
239- (embed_lib_fd >= 0 ) ? std::make_shared<sandbox2::Executor>(
240- embed_lib_fd, args, EnvironmentVariables ())
241- : std::make_shared<sandbox2::Executor>(
242- lib_path, args, EnvironmentVariables ());
243-
244- fork_client_shared ().client_ =
245- fork_client_shared ().executor_ ->StartForkServer ();
246-
247- if (!fork_client_shared ().client_ ) {
248- LOG (ERROR ) << " Could not start forkserver" ;
249- return absl::UnavailableError (" Could not start the forkserver" );
250- }
251- }
252- fork_client_executor = fork_client_shared ().executor_ ;
253- fork_client = fork_client_shared ().client_ ;
254- }
255-
256- std::unique_ptr<sandbox2::Policy> s2p;
257- if (config_.sandbox2 .policy ) {
258- s2p = std::make_unique<sandbox2::Policy>(*config_.sandbox2 .policy );
259- } else {
260- sandbox2::PolicyBuilder policy_builder =
261- Sandbox2Config::DefaultPolicyBuilder ();
262- if (config_.sandbox2 .use_unotify_monitor ) {
263- policy_builder.CollectStacktracesOnSignal (false );
264- }
265- s2p = policy_builder.BuildOrDie ();
266- }
267-
268- // Spawn new process from the forkserver.
269- auto executor = std::make_unique<sandbox2::Executor>(fork_client.get ());
270-
271- executor
272- // The client.cc code is capable of enabling sandboxing on its own.
273- ->set_enable_sandbox_before_exec (false )
274- // By default, set cwd to "/", can be changed in ModifyExecutor().
275- .set_cwd (" /" );
276- // Disable time limits.
277- *executor->limits () = Sandbox2Config::DefaultLimits ();
278-
279- // Modify the executor, e.g. by setting custom limits and IPC.
280- ApplySandbox2Config (executor.get ());
281- MapFileDescriptors (executor.get ());
282-
283- s2_ = std::make_unique<sandbox2::Sandbox2>(std::move (executor),
284- std::move (s2p), CreateNotifier ());
285- if (config_.sandbox2 .use_unotify_monitor ) {
286- SAPI_RETURN_IF_ERROR (s2_->EnableUnotifyMonitor ());
287- }
288- s2_awaited_ = false ;
289- auto res = s2_->RunAsync ();
290-
291- comms_ = s2_->comms ();
292- pid_ = s2_->pid ();
293-
294- rpc_channel_ = std::make_unique<Sandbox2RPCChannel>(comms_, pid_);
295-
296- if (!res) {
297- // Allow recovering from a bad fork client state.
298- {
299- absl::MutexLock lock (fork_client_shared ().mu_ );
300- fork_client_shared ().client_ .reset ();
301- }
302- sandbox2::Result result = s2_->AwaitResult ();
303- LOG (ERROR ) << " Could not start the sandbox: " << result.ToString ();
304- return absl::UnavailableError (
305- absl::StrCat (" Could not start the sandbox: " , result.ToString ()));
306- }
307- return absl::OkStatus ();
308- }
309-
310- bool Sandbox::is_active () const { return s2_ && !s2_->IsTerminated (); }
311-
312- absl::Status Sandbox::Allocate (v::Var* var, bool automatic_free) {
112+ absl::Status SandboxBase::Allocate (v::Var* var, bool automatic_free) {
313113 if (!is_active ()) {
314114 return absl::UnavailableError (" Sandbox not active" );
315115 }
316116 return var->Allocate (rpc_channel (), automatic_free);
317117}
318118
319- absl::Status Sandbox ::Free (v::Var* var) {
119+ absl::Status SandboxBase ::Free (v::Var* var) {
320120 if (!is_active ()) {
321121 return absl::UnavailableError (" Sandbox not active" );
322122 }
323123 return var->Free (rpc_channel ());
324124}
325125
326- absl::Status Sandbox ::SynchronizePtrBefore (v::Ptr* p) {
126+ absl::Status SandboxBase ::SynchronizePtrBefore (v::Ptr* p) {
327127 if (!is_active ()) {
328128 return absl::UnavailableError (" Sandbox not active" );
329129 }
@@ -352,7 +152,7 @@ absl::Status Sandbox::SynchronizePtrBefore(v::Ptr* p) {
352152 return p->GetPointedVar ()->TransferToSandboxee (rpc_channel ());
353153}
354154
355- absl::Status Sandbox ::SynchronizePtrAfter (v::Ptr* p) const {
155+ absl::Status SandboxBase ::SynchronizePtrAfter (v::Ptr* p) const {
356156 if (!is_active ()) {
357157 return absl::UnavailableError (" Sandbox not active" );
358158 }
@@ -377,7 +177,7 @@ absl::Status Sandbox::SynchronizePtrAfter(v::Ptr* p) const {
377177 return p->GetPointedVar ()->TransferFromSandboxee (rpc_channel ());
378178}
379179
380- absl::Status Sandbox ::Call (
180+ absl::Status SandboxBase ::Call (
381181 const std::string& func, v::Callable* ret,
382182 std::initializer_list<internal::PtrOrCallable> args) {
383183 if (!is_active ()) {
@@ -446,7 +246,7 @@ absl::Status Sandbox::Call(
446246 // Call & receive data.
447247 FuncRet fret;
448248 SAPI_RETURN_IF_ERROR (
449- rpc_channel_ ->Call (rfcall, comms::kMsgCall , &fret, rfcall.ret_type ));
249+ rpc_channel () ->Call (rfcall, comms::kMsgCall , &fret, rfcall.ret_type ));
450250
451251 if (fret.ret_type == v::Type::kFloat ) {
452252 memcpy (ret->GetLocal (), &fret.float_val ,
@@ -473,38 +273,38 @@ absl::Status Sandbox::Call(
473273 return absl::OkStatus ();
474274}
475275
476- absl::Status Sandbox ::Symbol (const char * symname, void ** addr) {
276+ absl::Status SandboxBase ::Symbol (const char * symname, void ** addr) {
477277 if (!is_active ()) {
478278 return absl::UnavailableError (" Sandbox not active" );
479279 }
480- return rpc_channel_ ->Symbol (symname, addr);
280+ return rpc_channel () ->Symbol (symname, addr);
481281}
482282
483- absl::Status Sandbox ::TransferToSandboxee (v::Var* var) {
283+ absl::Status SandboxBase ::TransferToSandboxee (v::Var* var) {
484284 if (!is_active ()) {
485285 return absl::UnavailableError (" Sandbox not active" );
486286 }
487287 return var->TransferToSandboxee (rpc_channel ());
488288}
489289
490- absl::Status Sandbox ::TransferFromSandboxee (v::Var* var) {
290+ absl::Status SandboxBase ::TransferFromSandboxee (v::Var* var) {
491291 if (!is_active ()) {
492292 return absl::UnavailableError (" Sandbox not active" );
493293 }
494294 return var->TransferFromSandboxee (rpc_channel ());
495295}
496296
497297absl::StatusOr<std::unique_ptr<sapi::v::Array<const uint8_t >>>
498- Sandbox ::AllocateAndTransferToSandboxee (absl::Span<const uint8_t > buffer) {
298+ SandboxBase ::AllocateAndTransferToSandboxee (absl::Span<const uint8_t > buffer) {
499299 auto sapi_buffer = std::make_unique<sapi::v::Array<const uint8_t >>(
500300 buffer.data (), buffer.size ());
501301 SAPI_RETURN_IF_ERROR (Allocate (sapi_buffer.get (), /* automatic_free=*/ true ));
502302 SAPI_RETURN_IF_ERROR (TransferToSandboxee (sapi_buffer.get ()));
503303 return sapi_buffer;
504304}
505305
506- absl::StatusOr<std::string> Sandbox ::GetCString (const v::RemotePtr& str,
507- size_t max_length) {
306+ absl::StatusOr<std::string> SandboxBase ::GetCString (const v::RemotePtr& str,
307+ size_t max_length) {
508308 if (!is_active ()) {
509309 return absl::UnavailableError (" Sandbox not active" );
510310 }
@@ -532,20 +332,4 @@ absl::StatusOr<std::string> Sandbox::GetCString(const v::RemotePtr& str,
532332 return buffer;
533333}
534334
535- const sandbox2::Result& Sandbox::AwaitResult () {
536- if (s2_ && !s2_awaited_) {
537- result_ = s2_->AwaitResult ();
538- s2_awaited_ = true ;
539- }
540- return result_;
541- }
542-
543- absl::Status Sandbox::SetWallTimeLimit (absl::Duration limit) const {
544- if (!is_active ()) {
545- return absl::UnavailableError (" Sandbox not active" );
546- }
547- s2_->set_walltime_limit (limit);
548- return absl::OkStatus ();
549- }
550-
551335} // namespace sapi
0 commit comments