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 #ifndef SANDBOXED_API_SANDBOX_H_ 16 #define SANDBOXED_API_SANDBOX_H_ 17 18 #include <ctime> 19 #include <initializer_list> 20 #include <memory> 21 #include <string> 22 #include <vector> 23 24 #include "sandboxed_api/file_toc.h" 25 #include "absl/base/macros.h" 26 #include "absl/log/globals.h" 27 #include "absl/log/log.h" 28 #include "absl/status/status.h" 29 #include "absl/status/statusor.h" 30 #include "absl/time/time.h" 31 #include "sandboxed_api/config.h" 32 #include "sandboxed_api/rpcchannel.h" 33 #include "sandboxed_api/sandbox2/client.h" 34 #include "sandboxed_api/sandbox2/comms.h" 35 #include "sandboxed_api/sandbox2/policy.h" 36 #include "sandboxed_api/sandbox2/policybuilder.h" 37 #include "sandboxed_api/sandbox2/sandbox2.h" 38 #include "sandboxed_api/vars.h" 39 40 namespace sapi { 41 42 // The Sandbox class represents the sandboxed library. It provides users with 43 // means to communicate with it (make function calls, transfer memory). 44 class Sandbox { 45 public: Sandbox(const FileToc * embed_lib_toc)46 explicit Sandbox(const FileToc* embed_lib_toc) 47 : embed_lib_toc_(embed_lib_toc) {} 48 49 Sandbox(const Sandbox&) = delete; 50 Sandbox& operator=(const Sandbox&) = delete; 51 52 virtual ~Sandbox(); 53 54 // Initializes a new sandboxing session. 55 absl::Status Init(bool use_unotify_monitor = false); 56 57 // Returns whether the current sandboxing session is active. 58 bool is_active() const; 59 60 // Terminates the current sandboxing session (if it exists). 61 void Terminate(bool attempt_graceful_exit = true); 62 63 // Restarts the sandbox. Restart(bool attempt_graceful_exit)64 absl::Status Restart(bool attempt_graceful_exit) { 65 Terminate(attempt_graceful_exit); 66 return Init(); 67 } 68 comms()69 sandbox2::Comms* comms() const { return comms_; } 70 rpc_channel()71 RPCChannel* rpc_channel() const { return rpc_channel_.get(); } 72 pid()73 int pid() const { return pid_; } 74 75 // Synchronizes the underlying memory for the pointer before the call. 76 absl::Status SynchronizePtrBefore(v::Callable* ptr); 77 78 // Synchronizes the underlying memory for pointer after the call. 79 absl::Status SynchronizePtrAfter(v::Callable* ptr) const; 80 81 // Makes a call to the sandboxee. 82 template <typename... Args> Call(const std::string & func,v::Callable * ret,Args &&...args)83 absl::Status Call(const std::string& func, v::Callable* ret, Args&&... args) { 84 static_assert(sizeof...(Args) <= FuncCall::kArgsMax, 85 "Too many arguments to sapi::Sandbox::Call()"); 86 return Call(func, ret, {std::forward<Args>(args)...}); 87 } 88 absl::Status Call(const std::string& func, v::Callable* ret, 89 std::initializer_list<v::Callable*> args); 90 91 // Allocates memory in the sandboxee, automatic_free indicates whether the 92 // memory should be freed on the remote side when the 'var' goes out of scope. 93 absl::Status Allocate(v::Var* var, bool automatic_free = false); 94 95 // Frees memory in the sandboxee. 96 absl::Status Free(v::Var* var); 97 98 // Finds the address of a symbol in the sandboxee. 99 absl::Status Symbol(const char* symname, void** addr); 100 101 // Transfers memory (both directions). Status is returned (memory transfer 102 // succeeded/failed). 103 absl::Status TransferToSandboxee(v::Var* var); 104 absl::Status TransferFromSandboxee(v::Var* var); 105 106 absl::StatusOr<std::string> GetCString(const v::RemotePtr& str, 107 size_t max_length = 10ULL 108 << 20 /* 10 MiB*/ 109 ); 110 111 // Waits until the sandbox terminated and returns the result. 112 const sandbox2::Result& AwaitResult(); result()113 const sandbox2::Result& result() const { return result_; } 114 115 absl::Status SetWallTimeLimit(absl::Duration limit) const; 116 117 protected: 118 119 // Gets extra arguments to be passed to the sandboxee. GetArgs(std::vector<std::string> * args)120 virtual void GetArgs(std::vector<std::string>* args) const { 121 args->push_back(absl::StrCat("--stderrthreshold=", 122 static_cast<int>(absl::StderrThreshold()))); 123 } 124 125 private: 126 // Gets the environment variables passed to the sandboxee. GetEnvs(std::vector<std::string> * envs)127 virtual void GetEnvs(std::vector<std::string>* envs) const { 128 // Do nothing by default. 129 } 130 131 // Returns the sandbox policy. Subclasses can modify the default policy 132 // builder, or return a completely new policy. 133 virtual std::unique_ptr<sandbox2::Policy> ModifyPolicy( 134 sandbox2::PolicyBuilder* builder); 135 136 // Path of the sandboxee: 137 // - relative to runfiles directory: ::sapi::GetDataDependencyFilePath() 138 // will be applied to it, 139 // - absolute: will be used as is. GetLibPath()140 virtual std::string GetLibPath() const { return ""; } 141 142 // Modifies the Executor object if needed. ModifyExecutor(sandbox2::Executor * executor)143 virtual void ModifyExecutor(sandbox2::Executor* executor) { 144 // Do nothing by default. 145 } 146 147 // Provides a custom notifier for sandboxee events. May return nullptr. CreateNotifier()148 virtual std::unique_ptr<sandbox2::Notify> CreateNotifier() { return nullptr; } 149 150 // Exits the sandboxee. 151 void Exit() const; 152 153 // The client to the library forkserver. 154 std::unique_ptr<sandbox2::ForkClient> fork_client_; 155 std::unique_ptr<sandbox2::Executor> forkserver_executor_; 156 157 // The main sandbox2::Sandbox2 object. 158 std::unique_ptr<sandbox2::Sandbox2> s2_; 159 // Marks whether Sandbox2 result was already fetched. 160 // We cannot just delete s2_ as Terminate might be called from another thread 161 // and comms object can be still in use then. 162 bool s2_awaited_ = false; 163 164 // Result of the most recent sandbox execution 165 sandbox2::Result result_; 166 167 // Comms with the sandboxee. 168 sandbox2::Comms* comms_ = nullptr; 169 // RPCChannel object. 170 std::unique_ptr<RPCChannel> rpc_channel_; 171 // The main pid of the sandboxee. 172 pid_t pid_ = 0; 173 174 // FileTOC with the embedded library, takes precedence over GetLibPath if 175 // present (not nullptr). 176 const FileToc* embed_lib_toc_; 177 }; 178 179 } // namespace sapi 180 181 #endif // SANDBOXED_API_SANDBOX_H_ 182