| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "mandoline/app/desktop/linux_sandbox.h" | |
| 6 | |
| 7 #include <fcntl.h> | |
| 8 #include <sys/syscall.h> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/debug/leak_annotations.h" | |
| 12 #include "base/posix/eintr_wrapper.h" | |
| 13 #include "base/rand_util.h" | |
| 14 #include "base/sys_info.h" | |
| 15 #include "sandbox/linux/bpf_dsl/policy.h" | |
| 16 #include "sandbox/linux/bpf_dsl/trap_registry.h" | |
| 17 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" | |
| 18 #include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h" | |
| 19 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | |
| 20 #include "sandbox/linux/services/credentials.h" | |
| 21 #include "sandbox/linux/services/namespace_sandbox.h" | |
| 22 #include "sandbox/linux/services/proc_util.h" | |
| 23 | |
| 24 using sandbox::syscall_broker::BrokerFilePermission; | |
| 25 | |
| 26 namespace mandoline { | |
| 27 | |
| 28 namespace { | |
| 29 | |
| 30 intptr_t SandboxSIGSYSHandler(const struct sandbox::arch_seccomp_data& args, | |
| 31 void* aux) { | |
| 32 RAW_CHECK(aux); | |
| 33 const sandbox::syscall_broker::BrokerProcess* broker_process = | |
| 34 static_cast<const sandbox::syscall_broker::BrokerProcess*>(aux); | |
| 35 switch (args.nr) { | |
| 36 case __NR_access: | |
| 37 return broker_process->Access(reinterpret_cast<const char*>(args.args[0]), | |
| 38 static_cast<int>(args.args[1])); | |
| 39 case __NR_open: | |
| 40 return broker_process->Open(reinterpret_cast<const char*>(args.args[0]), | |
| 41 static_cast<int>(args.args[1])); | |
| 42 case __NR_faccessat: | |
| 43 if (static_cast<int>(args.args[0]) == AT_FDCWD) { | |
| 44 return broker_process->Access( | |
| 45 reinterpret_cast<const char*>(args.args[1]), | |
| 46 static_cast<int>(args.args[2])); | |
| 47 } else { | |
| 48 return -EPERM; | |
| 49 } | |
| 50 case __NR_openat: | |
| 51 // Allow using openat() as open(). | |
| 52 if (static_cast<int>(args.args[0]) == AT_FDCWD) { | |
| 53 return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), | |
| 54 static_cast<int>(args.args[2])); | |
| 55 } else { | |
| 56 return -EPERM; | |
| 57 } | |
| 58 default: | |
| 59 RAW_CHECK(false); | |
| 60 return -ENOSYS; | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 class SandboxPolicy : public sandbox::bpf_dsl::Policy { | |
| 65 public: | |
| 66 explicit SandboxPolicy(sandbox::syscall_broker::BrokerProcess* broker_process) | |
| 67 : broker_process_(broker_process) {} | |
| 68 ~SandboxPolicy() override {} | |
| 69 | |
| 70 // Overridden from sandbox::bpf_dsl::Policy: | |
| 71 sandbox::bpf_dsl::ResultExpr EvaluateSyscall(int sysno) const override { | |
| 72 // This policy is only advisory/for noticing FS access for the moment. | |
| 73 switch (sysno) { | |
| 74 case __NR_access: | |
| 75 case __NR_open: | |
| 76 case __NR_faccessat: | |
| 77 case __NR_openat: | |
| 78 return sandbox::bpf_dsl::Trap(SandboxSIGSYSHandler, broker_process_); | |
| 79 } | |
| 80 | |
| 81 return sandbox::bpf_dsl::Allow(); | |
| 82 } | |
| 83 | |
| 84 private: | |
| 85 // Not owned. | |
| 86 const sandbox::syscall_broker::BrokerProcess* broker_process_; | |
| 87 DISALLOW_COPY_AND_ASSIGN(SandboxPolicy); | |
| 88 }; | |
| 89 | |
| 90 } // namespace | |
| 91 | |
| 92 LinuxSandbox::LinuxSandbox(const std::vector<BrokerFilePermission>& permissions) | |
| 93 : broker_(new sandbox::syscall_broker::BrokerProcess(EPERM, permissions)) { | |
| 94 broker_->Init( | |
| 95 base::Bind<bool (*)()>(&sandbox::Credentials::DropAllCapabilities)); | |
| 96 policy_.reset(new SandboxPolicy(broker_.get())); | |
| 97 } | |
| 98 | |
| 99 LinuxSandbox::~LinuxSandbox() {} | |
| 100 | |
| 101 // static | |
| 102 std::vector<BrokerFilePermission> LinuxSandbox::GetPermissions() { | |
| 103 std::vector<BrokerFilePermission> permissions; | |
| 104 permissions.push_back(BrokerFilePermission::ReadOnly("/dev/urandom")); | |
| 105 permissions.push_back(BrokerFilePermission::ReadOnly("/etc/ld.so.cache")); | |
| 106 permissions.push_back(BrokerFilePermission::ReadOnlyRecursive("/lib/")); | |
| 107 permissions.push_back(BrokerFilePermission::ReadOnlyRecursive("/usr/lib/")); | |
| 108 return permissions; | |
| 109 } | |
| 110 | |
| 111 void LinuxSandbox::Warmup() { | |
| 112 proc_fd_ = sandbox::ProcUtil::OpenProc(); | |
| 113 warmed_up_ = true; | |
| 114 } | |
| 115 | |
| 116 void LinuxSandbox::EngageNamespaceSandbox() { | |
| 117 CHECK(warmed_up_); | |
| 118 CHECK_EQ(1, getpid()); | |
| 119 CHECK(sandbox::NamespaceSandbox::InNewPidNamespace()); | |
| 120 CHECK(sandbox::Credentials::MoveToNewUserNS()); | |
| 121 CHECK(sandbox::Credentials::DropFileSystemAccess(proc_fd_.get())); | |
| 122 CHECK(sandbox::Credentials::DropAllCapabilities(proc_fd_.get())); | |
| 123 } | |
| 124 | |
| 125 void LinuxSandbox::EngageSeccompSandbox() { | |
| 126 CHECK(warmed_up_); | |
| 127 sandbox::SandboxBPF sandbox(policy_.release()); | |
| 128 base::ScopedFD proc_fd(HANDLE_EINTR( | |
| 129 openat(proc_fd_.get(), ".", O_RDONLY | O_DIRECTORY | O_CLOEXEC))); | |
| 130 CHECK(proc_fd.is_valid()); | |
| 131 sandbox.SetProcFd(proc_fd.Pass()); | |
| 132 CHECK( | |
| 133 sandbox.StartSandbox(sandbox::SandboxBPF::SeccompLevel::SINGLE_THREADED)) | |
| 134 << "Starting the process with a sandbox failed. Missing kernel support."; | |
| 135 | |
| 136 // The Broker is now bound to this process and should only be destroyed when | |
| 137 // the process exits or is killed. | |
| 138 ANNOTATE_LEAKING_OBJECT_PTR(broker_.release()); | |
| 139 } | |
| 140 | |
| 141 void LinuxSandbox::Seal() { | |
| 142 proc_fd_.reset(); | |
| 143 } | |
| 144 | |
| 145 } // namespace mandoline | |
| OLD | NEW |