5050#include " absl/strings/string_view.h"
5151#include " sandboxed_api/config.h"
5252#include " sandboxed_api/sandbox2/buffer.h"
53+ #include " sandboxed_api/sandbox2/client.pb.h"
5354#include " sandboxed_api/sandbox2/comms.h"
5455#include " sandboxed_api/sandbox2/logsink.h"
5556#include " sandboxed_api/sandbox2/network_proxy/client.h"
@@ -189,6 +190,7 @@ std::string Client::GetFdMapEnvVar() const {
189190}
190191
191192void Client::PrepareEnvironment (int * preserved_fd) {
193+ ReceiveClientConfig ();
192194 SetUpIPC (preserved_fd);
193195 SetUpCwd ();
194196}
@@ -204,41 +206,19 @@ void Client::SandboxMeHere() {
204206}
205207
206208void Client::SetUpCwd () {
207- {
208- // Get the current working directory to check if we are in a mount
209- // namespace.
210- // Note: glibc 2.27 no longer returns a relative path in that case, but
211- // fails with ENOENT and returns a nullptr instead. The code still
212- // needs to run on lower version for the time being.
213- char cwd_buf[PATH_MAX + 1 ] = {0 };
214- char * cwd = getcwd (cwd_buf, ABSL_ARRAYSIZE (cwd_buf));
215- SAPI_RAW_PCHECK (cwd != nullptr || errno == ENOENT,
216- " no current working directory" );
217-
218- // Outside of the mount namespace, the path is of the form
219- // '(unreachable)/...'. Only check for the slash, since Linux might make up
220- // other prefixes in the future.
221- if (errno == ENOENT || cwd_buf[0 ] != ' /' ) {
222- SAPI_RAW_VLOG (1 , " chdir into mount namespace, cwd was '%s'" , cwd_buf);
223- // If we are in a mount namespace but fail to chdir, then it can lead to a
224- // sandbox escape -- we need to fail with FATAL if the chdir fails.
225- SAPI_RAW_PCHECK (chdir (" /" ) != -1 , " corrective chdir" );
226- }
227- }
228-
229209 // Receive the user-supplied current working directory and change into it.
230- std::string cwd;
231- SAPI_RAW_CHECK (comms_-> RecvString (&cwd), " receiving working directory " ) ;
232- if (!cwd. empty ()) {
233- // On the other hand this chdir can fail without a sandbox escape. It will
234- // probably not have the intended behavior though.
235- if ( chdir (cwd. c_str ()) == - 1 && SAPI_RAW_VLOG_IS_ON ( 1 )) {
236- SAPI_RAW_PLOG (
237- INFO,
238- " chdir(%s) failed, falling back to previous cwd or / (with "
239- " namespaces). Use Executor::SetCwd() to set a working directory " ,
240- cwd. c_str ());
241- }
210+ if (client_config_. cwd (). empty ()) {
211+ return ;
212+ }
213+ std::string cwd (client_config_. cwd ());
214+ // This chdir can fail without a sandbox escape. It will probably not have
215+ // the intended behavior though.
216+ if ( chdir (cwd. c_str ()) == - 1 && SAPI_RAW_VLOG_IS_ON ( 1 )) {
217+ SAPI_RAW_PLOG (
218+ INFO,
219+ " chdir(%s) failed, falling back to previous cwd or / (with "
220+ " namespaces). Use Executor::SetCwd() to set a working directory " ,
221+ cwd. c_str ());
242222 }
243223}
244224
@@ -314,9 +294,12 @@ void Client::SetUpIPC(int* preserved_fd) {
314294}
315295
316296void Client::ReceivePolicy () {
317- std::vector<uint8_t > bytes;
318- SAPI_RAW_CHECK (comms_->RecvBytes (&bytes), " receive bytes" );
319- policy_ = std::move (bytes);
297+ SAPI_RAW_CHECK (comms_->RecvBytes (&policy_), " receive bytes" );
298+ }
299+
300+ void Client::ReceiveClientConfig () {
301+ SAPI_RAW_CHECK (comms_->RecvProtoBuf (&client_config_),
302+ " receive client config" );
320303}
321304
322305void Client::ApplyPolicyAndBecomeTracee () {
@@ -325,18 +308,13 @@ void Client::ApplyPolicyAndBecomeTracee() {
325308 // this function does nothing.
326309 sanitizer::WaitForSanitizer ();
327310
328- // Creds can be received w/o synchronization, once the connection is
329- // established.
330- pid_t cred_pid;
331- uid_t cred_uid ABSL_ATTRIBUTE_UNUSED;
332- gid_t cred_gid ABSL_ATTRIBUTE_UNUSED;
333- SAPI_RAW_CHECK (comms_->GetPeerCreds (&cred_pid, &cred_uid, &cred_gid),
334- " receiving credentials" );
335-
336- SAPI_RAW_CHECK (prctl (PR_SET_DUMPABLE, 1 ) == 0 ,
337- " setting PR_SET_DUMPABLE flag" );
338- if (prctl (PR_SET_PTRACER, cred_pid) == -1 ) {
339- SAPI_RAW_VLOG (1 , " No YAMA on this system. Continuing" );
311+ pid_t ptracer_tid = client_config_.ptracer_tid ();
312+ if (ptracer_tid > 0 ) {
313+ SAPI_RAW_CHECK (prctl (PR_SET_DUMPABLE, 1 ) == 0 ,
314+ " setting PR_SET_DUMPABLE flag" );
315+ if (prctl (PR_SET_PTRACER, ptracer_tid) == -1 ) {
316+ SAPI_RAW_VLOG (1 , " No YAMA on this system. Continuing" );
317+ }
340318 }
341319
342320 SAPI_RAW_CHECK (prctl (PR_SET_NO_NEW_PRIVS, 1 , 0 , 0 , 0 ) == 0 ,
@@ -364,7 +342,9 @@ void Client::ApplyPolicyAndBecomeTracee() {
364342 uint32_t message; // wait for confirmation
365343 SAPI_RAW_CHECK (comms_->RecvUint32 (&message),
366344 " receving confirmation from executor" );
367- bool allow_speculation = message & kAllowSpeculationBit ;
345+ SAPI_RAW_CHECK (message == kSandbox2MonitorReady ,
346+ " invalid confirmation from executor" );
347+ bool allow_speculation = client_config_.seccomp_allow_speculation ();
368348 if (!allow_speculation) {
369349 if constexpr (sapi::host_cpu::IsX8664 () || sapi::host_cpu::IsArm64 ()) {
370350 SAPI_RAW_PCHECK (prctl (PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS,
@@ -381,12 +361,13 @@ void Client::ApplyPolicyAndBecomeTracee() {
381361 }
382362 uint32_t seccomp_extra_flags =
383363 allow_speculation ? SECCOMP_FILTER_FLAG_SPEC_ALLOW : 0 ;
384- uint32_t monitor_type = message & kMonitorTypeMask ;
385- if (monitor_type == kSandbox2ClientUnotify ) {
364+ if (client_config_.monitor_type () == ClientConfig::CLIENT_MONITOR_UNOTIFY) {
386365 InitSeccompUnotify (prog, comms_, seccomp_extra_flags);
387366 } else {
388- SAPI_RAW_CHECK (monitor_type == kSandbox2ClientPtrace ,
389- " invalid confirmation from executor" );
367+ SAPI_RAW_CHECK (
368+ client_config_.monitor_type () == ClientConfig::CLIENT_MONITOR_PTRACE,
369+ absl::StrCat (" invalid monitor type: " , client_config_.monitor_type ())
370+ .c_str ());
390371 InitSeccompRegular (prog, seccomp_extra_flags);
391372 }
392373}
0 commit comments