| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sandbox/linux/services/credentials.h" | 5 #include "sandbox/linux/services/credentials.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <signal.h> | 8 #include <signal.h> |
| 9 #include <stdio.h> | 9 #include <stdio.h> |
| 10 #include <sys/syscall.h> | 10 #include <sys/syscall.h> |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 // CHECK() that an attempt to move to a new user namespace raised an expected | 103 // CHECK() that an attempt to move to a new user namespace raised an expected |
| 104 // errno. | 104 // errno. |
| 105 void CheckCloneNewUserErrno(int error) { | 105 void CheckCloneNewUserErrno(int error) { |
| 106 // EPERM can happen if already in a chroot. EUSERS if too many nested | 106 // EPERM can happen if already in a chroot. EUSERS if too many nested |
| 107 // namespaces are used. EINVAL for kernels that don't support the feature. | 107 // namespaces are used. EINVAL for kernels that don't support the feature. |
| 108 // Valgrind will ENOSYS unshare(). | 108 // Valgrind will ENOSYS unshare(). |
| 109 PCHECK(error == EPERM || error == EUSERS || error == EINVAL || | 109 PCHECK(error == EPERM || error == EUSERS || error == EINVAL || |
| 110 error == ENOSYS); | 110 error == ENOSYS); |
| 111 } | 111 } |
| 112 | 112 |
| 113 // Converts a Capability to the corresponding Linux CAP_XXX value. | 113 // Converts a LinuxCapability to the corresponding Linux CAP_XXX value. |
| 114 int CapabilityToKernelValue(Credentials::Capability cap) { | 114 int LinuxCapabilityToKernelValue(LinuxCapability cap) { |
| 115 switch (cap) { | 115 switch (cap) { |
| 116 case Credentials::Capability::SYS_CHROOT: | 116 case LinuxCapability::kCapSysChroot: |
| 117 return CAP_SYS_CHROOT; | 117 return CAP_SYS_CHROOT; |
| 118 case Credentials::Capability::SYS_ADMIN: | 118 case LinuxCapability::kCapSysAdmin: |
| 119 return CAP_SYS_ADMIN; | 119 return CAP_SYS_ADMIN; |
| 120 } | 120 } |
| 121 | 121 |
| 122 LOG(FATAL) << "Invalid Capability: " << static_cast<int>(cap); | 122 LOG(FATAL) << "Invalid LinuxCapability: " << static_cast<int>(cap); |
| 123 return 0; | 123 return 0; |
| 124 } | 124 } |
| 125 | 125 |
| 126 } // namespace. | 126 } // namespace. |
| 127 | 127 |
| 128 // static | |
| 129 bool Credentials::DropAllCapabilities(int proc_fd) { | 128 bool Credentials::DropAllCapabilities(int proc_fd) { |
| 130 if (!SetCapabilities(proc_fd, std::vector<Capability>())) { | 129 if (!SetCapabilities(proc_fd, std::vector<LinuxCapability>())) { |
| 131 return false; | 130 return false; |
| 132 } | 131 } |
| 133 | 132 |
| 134 CHECK(!HasAnyCapability()); | 133 CHECK(!HasAnyCapability()); |
| 135 return true; | 134 return true; |
| 136 } | 135 } |
| 137 | 136 |
| 138 // static | |
| 139 bool Credentials::DropAllCapabilities() { | 137 bool Credentials::DropAllCapabilities() { |
| 140 base::ScopedFD proc_fd(ProcUtil::OpenProc()); | 138 base::ScopedFD proc_fd(ProcUtil::OpenProc()); |
| 141 return Credentials::DropAllCapabilities(proc_fd.get()); | 139 return Credentials::DropAllCapabilities(proc_fd.get()); |
| 142 } | 140 } |
| 143 | 141 |
| 144 // static | 142 // static |
| 145 bool Credentials::DropAllCapabilitiesOnCurrentThread() { | |
| 146 return SetCapabilitiesOnCurrentThread(std::vector<Capability>()); | |
| 147 } | |
| 148 | |
| 149 // static | |
| 150 bool Credentials::SetCapabilitiesOnCurrentThread( | |
| 151 const std::vector<Capability>& caps) { | |
| 152 struct cap_hdr hdr = {}; | |
| 153 hdr.version = _LINUX_CAPABILITY_VERSION_3; | |
| 154 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; | |
| 155 | |
| 156 // Initially, cap has no capability flags set. Enable the effective and | |
| 157 // permitted flags only for the requested capabilities. | |
| 158 for (const Capability cap : caps) { | |
| 159 const int cap_num = CapabilityToKernelValue(cap); | |
| 160 const size_t index = CAP_TO_INDEX(cap_num); | |
| 161 const uint32_t mask = CAP_TO_MASK(cap_num); | |
| 162 data[index].effective |= mask; | |
| 163 data[index].permitted |= mask; | |
| 164 } | |
| 165 | |
| 166 return sys_capset(&hdr, data) == 0; | |
| 167 } | |
| 168 | |
| 169 // static | |
| 170 bool Credentials::SetCapabilities(int proc_fd, | 143 bool Credentials::SetCapabilities(int proc_fd, |
| 171 const std::vector<Capability>& caps) { | 144 const std::vector<LinuxCapability>& caps) { |
| 172 DCHECK_LE(0, proc_fd); | 145 DCHECK_LE(0, proc_fd); |
| 173 | 146 |
| 174 #if !defined(THREAD_SANITIZER) | 147 #if !defined(THREAD_SANITIZER) |
| 175 // With TSAN, accept to break the security model as it is a testing | 148 // With TSAN, accept to break the security model as it is a testing |
| 176 // configuration. | 149 // configuration. |
| 177 CHECK(ThreadHelpers::IsSingleThreaded(proc_fd)); | 150 CHECK(ThreadHelpers::IsSingleThreaded(proc_fd)); |
| 178 #endif | 151 #endif |
| 179 | 152 |
| 180 return SetCapabilitiesOnCurrentThread(caps); | 153 struct cap_hdr hdr = {}; |
| 154 hdr.version = _LINUX_CAPABILITY_VERSION_3; |
| 155 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; |
| 156 |
| 157 // Initially, cap has no capability flags set. Enable the effective and |
| 158 // permitted flags only for the requested capabilities. |
| 159 for (const LinuxCapability cap : caps) { |
| 160 const int cap_num = LinuxCapabilityToKernelValue(cap); |
| 161 const size_t index = CAP_TO_INDEX(cap_num); |
| 162 const uint32_t mask = CAP_TO_MASK(cap_num); |
| 163 data[index].effective |= mask; |
| 164 data[index].permitted |= mask; |
| 165 } |
| 166 |
| 167 return sys_capset(&hdr, data) == 0; |
| 181 } | 168 } |
| 182 | 169 |
| 183 bool Credentials::HasAnyCapability() { | 170 bool Credentials::HasAnyCapability() { |
| 184 struct cap_hdr hdr = {}; | 171 struct cap_hdr hdr = {}; |
| 185 hdr.version = _LINUX_CAPABILITY_VERSION_3; | 172 hdr.version = _LINUX_CAPABILITY_VERSION_3; |
| 186 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; | 173 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; |
| 187 | 174 |
| 188 PCHECK(sys_capget(&hdr, data) == 0); | 175 PCHECK(sys_capget(&hdr, data) == 0); |
| 189 | 176 |
| 190 for (size_t i = 0; i < arraysize(data); ++i) { | 177 for (size_t i = 0; i < arraysize(data); ++i) { |
| 191 if (data[i].effective || data[i].permitted || data[i].inheritable) { | 178 if (data[i].effective || data[i].permitted || data[i].inheritable) { |
| 192 return true; | 179 return true; |
| 193 } | 180 } |
| 194 } | 181 } |
| 195 | 182 |
| 196 return false; | 183 return false; |
| 197 } | 184 } |
| 198 | 185 |
| 199 bool Credentials::HasCapability(Capability cap) { | 186 bool Credentials::HasCapability(LinuxCapability cap) { |
| 200 struct cap_hdr hdr = {}; | 187 struct cap_hdr hdr = {}; |
| 201 hdr.version = _LINUX_CAPABILITY_VERSION_3; | 188 hdr.version = _LINUX_CAPABILITY_VERSION_3; |
| 202 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; | 189 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; |
| 203 | 190 |
| 204 PCHECK(sys_capget(&hdr, data) == 0); | 191 PCHECK(sys_capget(&hdr, data) == 0); |
| 205 | 192 |
| 206 const int cap_num = CapabilityToKernelValue(cap); | 193 const int cap_num = LinuxCapabilityToKernelValue(cap); |
| 207 const size_t index = CAP_TO_INDEX(cap_num); | 194 const size_t index = CAP_TO_INDEX(cap_num); |
| 208 const uint32_t mask = CAP_TO_MASK(cap_num); | 195 const uint32_t mask = CAP_TO_MASK(cap_num); |
| 209 | 196 |
| 210 return (data[index].effective | data[index].permitted | | 197 return (data[index].effective | data[index].permitted | |
| 211 data[index].inheritable) & | 198 data[index].inheritable) & |
| 212 mask; | 199 mask; |
| 213 } | 200 } |
| 214 | 201 |
| 215 // static | 202 // static |
| 216 bool Credentials::CanCreateProcessInNewUserNS() { | 203 bool Credentials::CanCreateProcessInNewUserNS() { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 CHECK_LE(0, proc_fd); | 275 CHECK_LE(0, proc_fd); |
| 289 | 276 |
| 290 CHECK(ChrootToSafeEmptyDir()); | 277 CHECK(ChrootToSafeEmptyDir()); |
| 291 CHECK(!base::DirectoryExists(base::FilePath("/proc"))); | 278 CHECK(!base::DirectoryExists(base::FilePath("/proc"))); |
| 292 CHECK(!ProcUtil::HasOpenDirectory(proc_fd)); | 279 CHECK(!ProcUtil::HasOpenDirectory(proc_fd)); |
| 293 // We never let this function fail. | 280 // We never let this function fail. |
| 294 return true; | 281 return true; |
| 295 } | 282 } |
| 296 | 283 |
| 297 } // namespace sandbox. | 284 } // namespace sandbox. |
| OLD | NEW |