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/capability.h> | 10 #include <sys/capability.h> |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 // EPERM can happen if already in a chroot. EUSERS if too many nested | 126 // EPERM can happen if already in a chroot. EUSERS if too many nested |
127 // namespaces are used. EINVAL for kernels that don't support the feature. | 127 // namespaces are used. EINVAL for kernels that don't support the feature. |
128 // Valgrind will ENOSYS unshare(). | 128 // Valgrind will ENOSYS unshare(). |
129 PCHECK(error == EPERM || error == EUSERS || error == EINVAL || | 129 PCHECK(error == EPERM || error == EUSERS || error == EINVAL || |
130 error == ENOSYS); | 130 error == ENOSYS); |
131 } | 131 } |
132 | 132 |
133 } // namespace. | 133 } // namespace. |
134 | 134 |
135 bool Credentials::DropAllCapabilities(int proc_fd) { | 135 bool Credentials::DropAllCapabilities(int proc_fd) { |
136 DCHECK_LE(0, proc_fd); | 136 if (!SetCapabilities(proc_fd, std::vector<cap_value_t>())) { |
137 #if !defined(THREAD_SANITIZER) | 137 return false; |
jln (very slow on Chromium)
2015/03/10 22:32:29
n.b. We used to never let this function fail and t
| |
138 // With TSAN, accept to break the security model as it is a testing | 138 } |
139 // configuration. | |
140 CHECK(ThreadHelpers::IsSingleThreaded(proc_fd)); | |
141 #endif | |
142 | 139 |
143 ScopedCap cap(cap_init()); | |
144 CHECK(cap); | |
145 PCHECK(0 == cap_set_proc(cap.get())); | |
146 CHECK(!HasAnyCapability()); | 140 CHECK(!HasAnyCapability()); |
147 // We never let this function fail. | |
148 return true; | 141 return true; |
149 } | 142 } |
150 | 143 |
151 bool Credentials::DropAllCapabilities() { | 144 bool Credentials::DropAllCapabilities() { |
152 base::ScopedFD proc_fd(ProcUtil::OpenProc()); | 145 base::ScopedFD proc_fd(ProcUtil::OpenProc()); |
153 return Credentials::DropAllCapabilities(proc_fd.get()); | 146 return Credentials::DropAllCapabilities(proc_fd.get()); |
154 } | 147 } |
155 | 148 |
149 // static | |
150 bool Credentials::SetCapabilities(int proc_fd, | |
151 const std::vector<cap_value_t>& caps) { | |
152 DCHECK_LE(0, proc_fd); | |
153 #if !defined(THREAD_SANITIZER) | |
154 // With TSAN, accept to break the security model as it is a testing | |
155 // configuration. | |
156 CHECK(ThreadHelpers::IsSingleThreaded(proc_fd)); | |
157 #endif | |
158 | |
159 sandbox::ScopedCap cap(cap_init()); | |
160 PCHECK(cap != nullptr); | |
161 | |
162 if (!caps.empty()) { | |
163 // Initially, cap has no capability flags set. Enable CAP_EFFECTIVE and | |
164 // CAP_PERMITTED only for the requested capabilities. | |
165 const cap_flag_t flags[] = {CAP_EFFECTIVE, CAP_PERMITTED}; | |
166 for (const cap_flag_t flag : flags) { | |
167 PCHECK(cap_set_flag(cap.get(), flag, caps.size(), &caps.at(0), CAP_SET) == | |
168 0); | |
169 } | |
170 } | |
171 | |
172 return cap_set_proc(cap.get()) == 0; | |
173 } | |
174 | |
156 bool Credentials::HasAnyCapability() { | 175 bool Credentials::HasAnyCapability() { |
157 ScopedCap current_cap(cap_get_proc()); | 176 ScopedCap current_cap(cap_get_proc()); |
158 CHECK(current_cap); | 177 CHECK(current_cap); |
159 ScopedCap empty_cap(cap_init()); | 178 ScopedCap empty_cap(cap_init()); |
160 CHECK(empty_cap); | 179 CHECK(empty_cap); |
161 return cap_compare(current_cap.get(), empty_cap.get()) != 0; | 180 return cap_compare(current_cap.get(), empty_cap.get()) != 0; |
162 } | 181 } |
163 | 182 |
183 bool Credentials::HasCapability(cap_value_t cap) { | |
184 ScopedCap current_cap(cap_get_proc()); | |
185 PCHECK(current_cap); | |
186 | |
187 cap_flag_value_t value; | |
188 const cap_flag_t flags[] = {CAP_EFFECTIVE, CAP_PERMITTED}; | |
189 for (const cap_flag_t flag : flags) { | |
190 PCHECK(cap_get_flag(current_cap.get(), cap, flag, &value) == 0); | |
191 if (value == CAP_SET) { | |
192 return true; | |
193 } | |
194 } | |
195 return false; | |
196 } | |
197 | |
164 scoped_ptr<std::string> Credentials::GetCurrentCapString() { | 198 scoped_ptr<std::string> Credentials::GetCurrentCapString() { |
165 ScopedCap current_cap(cap_get_proc()); | 199 ScopedCap current_cap(cap_get_proc()); |
166 CHECK(current_cap); | 200 CHECK(current_cap); |
167 ScopedCapText cap_text(cap_to_text(current_cap.get(), NULL)); | 201 ScopedCapText cap_text(cap_to_text(current_cap.get(), NULL)); |
168 CHECK(cap_text); | 202 CHECK(cap_text); |
169 return scoped_ptr<std::string> (new std::string(cap_text.get())); | 203 return scoped_ptr<std::string> (new std::string(cap_text.get())); |
170 } | 204 } |
171 | 205 |
172 // static | 206 // static |
173 bool Credentials::CanCreateProcessInNewUserNS() { | 207 bool Credentials::CanCreateProcessInNewUserNS() { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 CHECK_LE(0, proc_fd); | 279 CHECK_LE(0, proc_fd); |
246 | 280 |
247 CHECK(ChrootToSafeEmptyDir()); | 281 CHECK(ChrootToSafeEmptyDir()); |
248 CHECK(!base::DirectoryExists(base::FilePath("/proc"))); | 282 CHECK(!base::DirectoryExists(base::FilePath("/proc"))); |
249 CHECK(!ProcUtil::HasOpenDirectory(proc_fd)); | 283 CHECK(!ProcUtil::HasOpenDirectory(proc_fd)); |
250 // We never let this function fail. | 284 // We never let this function fail. |
251 return true; | 285 return true; |
252 } | 286 } |
253 | 287 |
254 } // namespace sandbox. | 288 } // namespace sandbox. |
OLD | NEW |