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 <cstddef> 19 #include <cstdint> 20 #include <ctime> 21 #include <initializer_list> 22 #include <memory> 23 #include <string> 24 #include <vector> 25 26 #include "sandboxed_api/file_toc.h" 27 #include "absl/base/attributes.h" 28 #include "absl/base/macros.h" 29 #include "absl/base/thread_annotations.h" 30 #include "absl/log/globals.h" 31 #include "absl/log/log.h" 32 #include "absl/status/status.h" 33 #include "absl/status/statusor.h" 34 #include "absl/strings/str_cat.h" 35 #include "absl/synchronization/mutex.h" 36 #include "absl/time/time.h" 37 #include "absl/types/span.h" 38 #include "sandboxed_api/config.h" 39 #include "sandboxed_api/rpcchannel.h" 40 #include "sandboxed_api/sandbox2/client.h" 41 #include "sandboxed_api/sandbox2/comms.h" 42 #include "sandboxed_api/sandbox2/policy.h" 43 #include "sandboxed_api/sandbox2/policybuilder.h" 44 #include "sandboxed_api/sandbox2/sandbox2.h" 45 #include "sandboxed_api/vars.h" 46 47 namespace sapi { 48 49 // Context holding, potentially shared, fork client. 50 class ForkClientContext { 51 public: ForkClientContext(const FileToc * embed_lib_toc)52 explicit ForkClientContext(const FileToc* embed_lib_toc) 53 : embed_lib_toc_(embed_lib_toc) {} 54 55 private: 56 friend class Sandbox; 57 const FileToc* embed_lib_toc_; 58 absl::Mutex mu_; 59 std::unique_ptr<sandbox2::ForkClient> client_ ABSL_GUARDED_BY(mu_); 60 std::unique_ptr<sandbox2::Executor> executor_ ABSL_GUARDED_BY(mu_); 61 }; 62 63 // The Sandbox class represents the sandboxed library. It provides users with 64 // means to communicate with it (make function calls, transfer memory). 65 class Sandbox { 66 public: Sandbox(ForkClientContext * fork_client_context ABSL_ATTRIBUTE_LIFETIME_BOUND)67 explicit Sandbox( 68 ForkClientContext* fork_client_context ABSL_ATTRIBUTE_LIFETIME_BOUND) 69 : fork_client_context_(fork_client_context) {} 70 71 explicit Sandbox(const FileToc* embed_lib_toc ABSL_ATTRIBUTE_LIFETIME_BOUND); 72 73 explicit Sandbox(std::nullptr_t); 74 75 Sandbox(const Sandbox&) = delete; 76 Sandbox& operator=(const Sandbox&) = delete; 77 78 virtual ~Sandbox(); 79 80 void SetForkClientContext(ForkClientContext* fork_client_context); 81 82 // Initializes a new sandboxing session. 83 absl::Status Init(bool use_unotify_monitor = false); 84 85 // Returns whether the current sandboxing session is active. 86 bool is_active() const; 87 88 // Terminates the current sandboxing session (if it exists). 89 void Terminate(bool attempt_graceful_exit = true); 90 91 // Restarts the sandbox. Restart(bool attempt_graceful_exit)92 absl::Status Restart(bool attempt_graceful_exit) { 93 Terminate(attempt_graceful_exit); 94 return Init(); 95 } 96 comms()97 sandbox2::Comms* comms() const { return comms_; } 98 rpc_channel()99 RPCChannel* rpc_channel() const { return rpc_channel_.get(); } 100 pid()101 int pid() const { return pid_; } 102 103 // Synchronizes the underlying memory for the pointer before the call. 104 absl::Status SynchronizePtrBefore(v::Callable* ptr); 105 106 // Synchronizes the underlying memory for pointer after the call. 107 absl::Status SynchronizePtrAfter(v::Callable* ptr) const; 108 109 // Makes a call to the sandboxee. 110 template <typename... Args> Call(const std::string & func,v::Callable * ret,Args &&...args)111 absl::Status Call(const std::string& func, v::Callable* ret, Args&&... args) { 112 static_assert(sizeof...(Args) <= FuncCall::kArgsMax, 113 "Too many arguments to sapi::Sandbox::Call()"); 114 return Call(func, ret, {std::forward<Args>(args)...}); 115 } 116 virtual absl::Status Call(const std::string& func, v::Callable* ret, 117 std::initializer_list<v::Callable*> args); 118 119 // Allocates memory in the sandboxee, automatic_free indicates whether the 120 // memory should be freed on the remote side when the 'var' goes out of scope. 121 absl::Status Allocate(v::Var* var, bool automatic_free = false); 122 123 // Frees memory in the sandboxee. 124 absl::Status Free(v::Var* var); 125 126 // Finds the address of a symbol in the sandboxee. 127 absl::Status Symbol(const char* symname, void** addr); 128 129 // Transfers memory to the sandboxee's address space from the hostcode. 130 // Returns the status of the operation. Requires a v::Var object to be set up 131 // with a suitable memory buffer allocated in the hostcode. 132 // 133 // Example Usage: 134 // std::string buffer(size_of_memory_in_sandboxee, ' '); 135 // sapi::v::Array<uint8_t> sapi_buffer( 136 // reinterpret_cast<uint8_t*>(buffer.data()), buffer.size()); 137 // SAPI_RETURN_IF_ERROR(sandbox.Allocate(&sapi_buffer)); 138 // SAPI_RETURN_IF_ERROR(sandbox.TransferFromSandboxee(&sapi_buffer)); 139 absl::Status TransferToSandboxee(v::Var* var); 140 141 // Transfers memory from the sandboxee's address space to the hostcode. 142 // Returns the status of the operation. Requires a v::Var object to be set up 143 // suitable memory buffer allocated in the hostcode. This call 144 // does not alter the memory in the sandboxee. It is therefore safe to 145 // const_cast `addr_of_memory_in_sandboxee` if necessary. 146 // 147 // Example Usage: 148 // std::string buffer(size_of_memory_in_sandboxee, ' '); 149 // sapi::v::Array<uint8_t> sapi_buffer( 150 // reinterpret_cast<uint8_t*>(buffer.data()), buffer.size()); 151 // sapi_buffer.SetRemote(addr_of_memory_in_sandboxee); 152 // SAPI_RETURN_IF_ERROR(sandbox.TransferFromSandboxee(&sapi_buffer)); 153 absl::Status TransferFromSandboxee(v::Var* var); 154 155 // Allocates and transfers a buffer to the sandboxee's address space from the 156 // hostcode. Returns a status on failure, or a unique_ptr to 157 // sapi::v::Array<const uint8_t> on success. 158 absl::StatusOr<std::unique_ptr<sapi::v::Array<const uint8_t>>> 159 AllocateAndTransferToSandboxee(absl::Span<const uint8_t> buffer); 160 161 absl::StatusOr<std::string> GetCString(const v::RemotePtr& str, 162 size_t max_length = 10ULL 163 << 20 /* 10 MiB*/ 164 ); 165 166 // Waits until the sandbox terminated and returns the result. 167 const sandbox2::Result& AwaitResult(); result()168 const sandbox2::Result& result() const { return result_; } 169 170 absl::Status SetWallTimeLimit(absl::Duration limit) const; 171 172 protected: 173 174 // Gets extra arguments to be passed to the sandboxee. GetArgs(std::vector<std::string> * args)175 virtual void GetArgs(std::vector<std::string>* args) const { 176 args->push_back(absl::StrCat("--stderrthreshold=", 177 static_cast<int>(absl::StderrThreshold()))); 178 } 179 180 // Gets the environment variables passed to the sandboxee. GetEnvs(std::vector<std::string> * envs)181 virtual void GetEnvs(std::vector<std::string>* envs) const { 182 // Do nothing by default. 183 } 184 185 private: 186 // Returns the sandbox policy. Subclasses can modify the default policy 187 // builder, or return a completely new policy. 188 virtual std::unique_ptr<sandbox2::Policy> ModifyPolicy( 189 sandbox2::PolicyBuilder* builder); 190 191 // Path of the sandboxee: 192 // - relative to runfiles directory: ::sapi::GetDataDependencyFilePath() 193 // will be applied to it, 194 // - absolute: will be used as is. GetLibPath()195 virtual std::string GetLibPath() const { return ""; } 196 197 // Modifies the Executor object if needed. ModifyExecutor(sandbox2::Executor * executor)198 virtual void ModifyExecutor(sandbox2::Executor* executor) { 199 // Do nothing by default. 200 } 201 202 // Provides a custom notifier for sandboxee events. May return nullptr. CreateNotifier()203 virtual std::unique_ptr<sandbox2::Notify> CreateNotifier() { return nullptr; } 204 205 // The main sandbox2::Sandbox2 object. 206 std::unique_ptr<sandbox2::Sandbox2> s2_; 207 // Marks whether Sandbox2 result was already fetched. 208 // We cannot just delete s2_ as Terminate might be called from another thread 209 // and comms object can be still in use then. 210 bool s2_awaited_ = false; 211 212 // Result of the most recent sandbox execution 213 sandbox2::Result result_; 214 215 // Comms with the sandboxee. 216 sandbox2::Comms* comms_ = nullptr; 217 // RPCChannel object. 218 std::unique_ptr<RPCChannel> rpc_channel_; 219 // The main pid of the sandboxee. 220 pid_t pid_ = 0; 221 222 // FileTOC with the embedded library, takes precedence over GetLibPath if 223 // present (not nullptr). 224 const FileToc* embed_lib_toc_; 225 226 ForkClientContext* fork_client_context_; 227 // Set if the object owns the client context instance. 228 std::unique_ptr<ForkClientContext> owned_fork_client_context_; 229 }; 230 231 } // namespace sapi 232 233 #endif // SANDBOXED_API_SANDBOX_H_ 234