| 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 | 
|---|