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 LinuxCapability to the corresponding Linux CAP_XXX value. | 113 // Converts a Capability to the corresponding Linux CAP_XXX value. |
114 int LinuxCapabilityToKernelValue(LinuxCapability cap) { | 114 int CapabilityToKernelValue(Credentials::Capability cap) { |
115 switch (cap) { | 115 switch (cap) { |
116 case LinuxCapability::kCapSysChroot: | 116 case Credentials::Capability::SYS_CHROOT: |
117 return CAP_SYS_CHROOT; | 117 return CAP_SYS_CHROOT; |
118 case LinuxCapability::kCapSysAdmin: | 118 case Credentials::Capability::SYS_ADMIN: |
119 return CAP_SYS_ADMIN; | 119 return CAP_SYS_ADMIN; |
120 } | 120 } |
121 | 121 |
122 LOG(FATAL) << "Invalid LinuxCapability: " << static_cast<int>(cap); | 122 LOG(FATAL) << "Invalid Capability: " << static_cast<int>(cap); |
123 return 0; | 123 return 0; |
124 } | 124 } |
125 | 125 |
126 } // namespace. | 126 } // namespace. |
127 | 127 |
| 128 // static |
128 bool Credentials::DropAllCapabilities(int proc_fd) { | 129 bool Credentials::DropAllCapabilities(int proc_fd) { |
129 if (!SetCapabilities(proc_fd, std::vector<LinuxCapability>())) { | 130 if (!SetCapabilities(proc_fd, std::vector<Capability>())) { |
130 return false; | 131 return false; |
131 } | 132 } |
132 | 133 |
133 CHECK(!HasAnyCapability()); | 134 CHECK(!HasAnyCapability()); |
134 return true; | 135 return true; |
135 } | 136 } |
136 | 137 |
| 138 // static |
137 bool Credentials::DropAllCapabilities() { | 139 bool Credentials::DropAllCapabilities() { |
138 base::ScopedFD proc_fd(ProcUtil::OpenProc()); | 140 base::ScopedFD proc_fd(ProcUtil::OpenProc()); |
139 return Credentials::DropAllCapabilities(proc_fd.get()); | 141 return Credentials::DropAllCapabilities(proc_fd.get()); |
140 } | 142 } |
141 | 143 |
142 // static | 144 // static |
143 bool Credentials::SetCapabilities(int proc_fd, | 145 bool Credentials::DropAllCapabilitiesOnCurrentThread() { |
144 const std::vector<LinuxCapability>& caps) { | 146 return SetCapabilitiesOnCurrentThread(std::vector<Capability>()); |
145 DCHECK_LE(0, proc_fd); | 147 } |
146 | 148 |
147 #if !defined(THREAD_SANITIZER) | 149 // static |
148 // With TSAN, accept to break the security model as it is a testing | 150 bool Credentials::SetCapabilitiesOnCurrentThread( |
149 // configuration. | 151 const std::vector<Capability>& caps) { |
150 CHECK(ThreadHelpers::IsSingleThreaded(proc_fd)); | |
151 #endif | |
152 | |
153 struct cap_hdr hdr = {}; | 152 struct cap_hdr hdr = {}; |
154 hdr.version = _LINUX_CAPABILITY_VERSION_3; | 153 hdr.version = _LINUX_CAPABILITY_VERSION_3; |
155 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; | 154 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; |
156 | 155 |
157 // Initially, cap has no capability flags set. Enable the effective and | 156 // Initially, cap has no capability flags set. Enable the effective and |
158 // permitted flags only for the requested capabilities. | 157 // permitted flags only for the requested capabilities. |
159 for (const LinuxCapability cap : caps) { | 158 for (const Capability cap : caps) { |
160 const int cap_num = LinuxCapabilityToKernelValue(cap); | 159 const int cap_num = CapabilityToKernelValue(cap); |
161 const size_t index = CAP_TO_INDEX(cap_num); | 160 const size_t index = CAP_TO_INDEX(cap_num); |
162 const uint32_t mask = CAP_TO_MASK(cap_num); | 161 const uint32_t mask = CAP_TO_MASK(cap_num); |
163 data[index].effective |= mask; | 162 data[index].effective |= mask; |
164 data[index].permitted |= mask; | 163 data[index].permitted |= mask; |
165 } | 164 } |
166 | 165 |
167 return sys_capset(&hdr, data) == 0; | 166 return sys_capset(&hdr, data) == 0; |
168 } | 167 } |
169 | 168 |
| 169 // static |
| 170 bool Credentials::SetCapabilities(int proc_fd, |
| 171 const std::vector<Capability>& caps) { |
| 172 DCHECK_LE(0, proc_fd); |
| 173 |
| 174 #if !defined(THREAD_SANITIZER) |
| 175 // With TSAN, accept to break the security model as it is a testing |
| 176 // configuration. |
| 177 CHECK(ThreadHelpers::IsSingleThreaded(proc_fd)); |
| 178 #endif |
| 179 |
| 180 return SetCapabilitiesOnCurrentThread(caps); |
| 181 } |
| 182 |
170 bool Credentials::HasAnyCapability() { | 183 bool Credentials::HasAnyCapability() { |
171 struct cap_hdr hdr = {}; | 184 struct cap_hdr hdr = {}; |
172 hdr.version = _LINUX_CAPABILITY_VERSION_3; | 185 hdr.version = _LINUX_CAPABILITY_VERSION_3; |
173 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; | 186 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; |
174 | 187 |
175 PCHECK(sys_capget(&hdr, data) == 0); | 188 PCHECK(sys_capget(&hdr, data) == 0); |
176 | 189 |
177 for (size_t i = 0; i < arraysize(data); ++i) { | 190 for (size_t i = 0; i < arraysize(data); ++i) { |
178 if (data[i].effective || data[i].permitted || data[i].inheritable) { | 191 if (data[i].effective || data[i].permitted || data[i].inheritable) { |
179 return true; | 192 return true; |
180 } | 193 } |
181 } | 194 } |
182 | 195 |
183 return false; | 196 return false; |
184 } | 197 } |
185 | 198 |
186 bool Credentials::HasCapability(LinuxCapability cap) { | 199 bool Credentials::HasCapability(Capability cap) { |
187 struct cap_hdr hdr = {}; | 200 struct cap_hdr hdr = {}; |
188 hdr.version = _LINUX_CAPABILITY_VERSION_3; | 201 hdr.version = _LINUX_CAPABILITY_VERSION_3; |
189 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; | 202 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}}; |
190 | 203 |
191 PCHECK(sys_capget(&hdr, data) == 0); | 204 PCHECK(sys_capget(&hdr, data) == 0); |
192 | 205 |
193 const int cap_num = LinuxCapabilityToKernelValue(cap); | 206 const int cap_num = CapabilityToKernelValue(cap); |
194 const size_t index = CAP_TO_INDEX(cap_num); | 207 const size_t index = CAP_TO_INDEX(cap_num); |
195 const uint32_t mask = CAP_TO_MASK(cap_num); | 208 const uint32_t mask = CAP_TO_MASK(cap_num); |
196 | 209 |
197 return (data[index].effective | data[index].permitted | | 210 return (data[index].effective | data[index].permitted | |
198 data[index].inheritable) & | 211 data[index].inheritable) & |
199 mask; | 212 mask; |
200 } | 213 } |
201 | 214 |
202 // static | 215 // static |
203 bool Credentials::CanCreateProcessInNewUserNS() { | 216 bool Credentials::CanCreateProcessInNewUserNS() { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 CHECK_LE(0, proc_fd); | 288 CHECK_LE(0, proc_fd); |
276 | 289 |
277 CHECK(ChrootToSafeEmptyDir()); | 290 CHECK(ChrootToSafeEmptyDir()); |
278 CHECK(!base::DirectoryExists(base::FilePath("/proc"))); | 291 CHECK(!base::DirectoryExists(base::FilePath("/proc"))); |
279 CHECK(!ProcUtil::HasOpenDirectory(proc_fd)); | 292 CHECK(!ProcUtil::HasOpenDirectory(proc_fd)); |
280 // We never let this function fail. | 293 // We never let this function fail. |
281 return true; | 294 return true; |
282 } | 295 } |
283 | 296 |
284 } // namespace sandbox. | 297 } // namespace sandbox. |
OLD | NEW |