Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1072)

Side by Side Diff: sandbox/linux/services/credentials.cc

Issue 1013463003: Update from https://crrev.com/320931 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sandbox/linux/services/credentials.h ('k') | sandbox/linux/services/credentials_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
11 #include <sys/syscall.h> 10 #include <sys/syscall.h>
12 #include <sys/types.h> 11 #include <sys/types.h>
13 #include <sys/wait.h> 12 #include <sys/wait.h>
14 #include <unistd.h> 13 #include <unistd.h>
15 14
16 #include "base/basictypes.h" 15 #include "base/basictypes.h"
17 #include "base/bind.h" 16 #include "base/bind.h"
18 #include "base/files/file_path.h" 17 #include "base/files/file_path.h"
19 #include "base/files/file_util.h" 18 #include "base/files/file_util.h"
20 #include "base/logging.h" 19 #include "base/logging.h"
21 #include "base/posix/eintr_wrapper.h" 20 #include "base/posix/eintr_wrapper.h"
22 #include "base/process/launch.h" 21 #include "base/process/launch.h"
23 #include "base/template_util.h" 22 #include "base/template_util.h"
24 #include "base/third_party/valgrind/valgrind.h" 23 #include "base/third_party/valgrind/valgrind.h"
25 #include "build/build_config.h" 24 #include "build/build_config.h"
26 #include "sandbox/linux/services/namespace_utils.h" 25 #include "sandbox/linux/services/namespace_utils.h"
27 #include "sandbox/linux/services/proc_util.h" 26 #include "sandbox/linux/services/proc_util.h"
28 #include "sandbox/linux/services/syscall_wrappers.h" 27 #include "sandbox/linux/services/syscall_wrappers.h"
29 #include "sandbox/linux/services/thread_helpers.h" 28 #include "sandbox/linux/services/thread_helpers.h"
29 #include "sandbox/linux/system_headers/capability.h"
30 30
31 namespace sandbox { 31 namespace sandbox {
32 32
33 namespace { 33 namespace {
34 34
35 bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; } 35 bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; }
36 36
37 struct CapFreeDeleter {
38 inline void operator()(cap_t cap) const {
39 int ret = cap_free(cap);
40 CHECK_EQ(0, ret);
41 }
42 };
43
44 // Wrapper to manage libcap2's cap_t type.
45 typedef scoped_ptr<typeof(*((cap_t)0)), CapFreeDeleter> ScopedCap;
46
47 struct CapTextFreeDeleter {
48 inline void operator()(char* cap_text) const {
49 int ret = cap_free(cap_text);
50 CHECK_EQ(0, ret);
51 }
52 };
53
54 // Wrapper to manage the result from libcap2's cap_from_text().
55 typedef scoped_ptr<char, CapTextFreeDeleter> ScopedCapText;
56
57 // Checks that the set of RES-uids and the set of RES-gids have 37 // Checks that the set of RES-uids and the set of RES-gids have
58 // one element each and return that element in |resuid| and |resgid| 38 // one element each and return that element in |resuid| and |resgid|
59 // respectively. It's ok to pass NULL as one or both of the ids. 39 // respectively. It's ok to pass NULL as one or both of the ids.
60 bool GetRESIds(uid_t* resuid, gid_t* resgid) { 40 bool GetRESIds(uid_t* resuid, gid_t* resgid) {
61 uid_t ruid, euid, suid; 41 uid_t ruid, euid, suid;
62 gid_t rgid, egid, sgid; 42 gid_t rgid, egid, sgid;
63 PCHECK(getresuid(&ruid, &euid, &suid) == 0); 43 PCHECK(getresuid(&ruid, &euid, &suid) == 0);
64 PCHECK(getresgid(&rgid, &egid, &sgid) == 0); 44 PCHECK(getresgid(&rgid, &egid, &sgid) == 0);
65 const bool uids_are_equal = (ruid == euid) && (ruid == suid); 45 const bool uids_are_equal = (ruid == euid) && (ruid == suid);
66 const bool gids_are_equal = (rgid == egid) && (rgid == sgid); 46 const bool gids_are_equal = (rgid == egid) && (rgid == sgid);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 // 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
124 // errno. 104 // errno.
125 void CheckCloneNewUserErrno(int error) { 105 void CheckCloneNewUserErrno(int error) {
126 // 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
127 // 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.
128 // Valgrind will ENOSYS unshare(). 108 // Valgrind will ENOSYS unshare().
129 PCHECK(error == EPERM || error == EUSERS || error == EINVAL || 109 PCHECK(error == EPERM || error == EUSERS || error == EINVAL ||
130 error == ENOSYS); 110 error == ENOSYS);
131 } 111 }
132 112
113 // Converts a LinuxCapability to the corresponding Linux CAP_XXX value.
114 int LinuxCapabilityToKernelValue(LinuxCapability cap) {
115 switch (cap) {
116 case LinuxCapability::kCapSysChroot:
117 return CAP_SYS_CHROOT;
118 case LinuxCapability::kCapSysAdmin:
119 return CAP_SYS_ADMIN;
120 }
121
122 LOG(FATAL) << "Invalid LinuxCapability: " << static_cast<int>(cap);
123 return 0;
124 }
125
133 } // namespace. 126 } // namespace.
134 127
135 bool Credentials::DropAllCapabilities(int proc_fd) { 128 bool Credentials::DropAllCapabilities(int proc_fd) {
136 DCHECK_LE(0, proc_fd); 129 if (!SetCapabilities(proc_fd, std::vector<LinuxCapability>())) {
137 #if !defined(THREAD_SANITIZER) 130 return false;
138 // With TSAN, accept to break the security model as it is a testing 131 }
139 // configuration.
140 CHECK(ThreadHelpers::IsSingleThreaded(proc_fd));
141 #endif
142 132
143 ScopedCap cap(cap_init());
144 CHECK(cap);
145 PCHECK(0 == cap_set_proc(cap.get()));
146 CHECK(!HasAnyCapability()); 133 CHECK(!HasAnyCapability());
147 // We never let this function fail.
148 return true; 134 return true;
149 } 135 }
150 136
151 bool Credentials::DropAllCapabilities() { 137 bool Credentials::DropAllCapabilities() {
152 base::ScopedFD proc_fd(ProcUtil::OpenProc()); 138 base::ScopedFD proc_fd(ProcUtil::OpenProc());
153 return Credentials::DropAllCapabilities(proc_fd.get()); 139 return Credentials::DropAllCapabilities(proc_fd.get());
154 } 140 }
155 141
156 bool Credentials::HasAnyCapability() { 142 // static
157 ScopedCap current_cap(cap_get_proc()); 143 bool Credentials::SetCapabilities(int proc_fd,
158 CHECK(current_cap); 144 const std::vector<LinuxCapability>& caps) {
159 ScopedCap empty_cap(cap_init()); 145 DCHECK_LE(0, proc_fd);
160 CHECK(empty_cap); 146
161 return cap_compare(current_cap.get(), empty_cap.get()) != 0; 147 #if !defined(THREAD_SANITIZER)
148 // With TSAN, accept to break the security model as it is a testing
149 // configuration.
150 CHECK(ThreadHelpers::IsSingleThreaded(proc_fd));
151 #endif
152
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;
162 } 168 }
163 169
164 scoped_ptr<std::string> Credentials::GetCurrentCapString() { 170 bool Credentials::HasAnyCapability() {
165 ScopedCap current_cap(cap_get_proc()); 171 struct cap_hdr hdr = {};
166 CHECK(current_cap); 172 hdr.version = _LINUX_CAPABILITY_VERSION_3;
167 ScopedCapText cap_text(cap_to_text(current_cap.get(), NULL)); 173 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
168 CHECK(cap_text); 174
169 return scoped_ptr<std::string> (new std::string(cap_text.get())); 175 PCHECK(sys_capget(&hdr, data) == 0);
176
177 for (size_t i = 0; i < arraysize(data); ++i) {
178 if (data[i].effective || data[i].permitted || data[i].inheritable) {
179 return true;
180 }
181 }
182
183 return false;
184 }
185
186 bool Credentials::HasCapability(LinuxCapability cap) {
187 struct cap_hdr hdr = {};
188 hdr.version = _LINUX_CAPABILITY_VERSION_3;
189 struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {{}};
190
191 PCHECK(sys_capget(&hdr, data) == 0);
192
193 const int cap_num = LinuxCapabilityToKernelValue(cap);
194 const size_t index = CAP_TO_INDEX(cap_num);
195 const uint32_t mask = CAP_TO_MASK(cap_num);
196
197 return (data[index].effective | data[index].permitted |
198 data[index].inheritable) &
199 mask;
170 } 200 }
171 201
172 // static 202 // static
173 bool Credentials::CanCreateProcessInNewUserNS() { 203 bool Credentials::CanCreateProcessInNewUserNS() {
174 // Valgrind will let clone(2) pass-through, but doesn't support unshare(), 204 // Valgrind will let clone(2) pass-through, but doesn't support unshare(),
175 // so always consider UserNS unsupported there. 205 // so always consider UserNS unsupported there.
176 if (IsRunningOnValgrind()) { 206 if (IsRunningOnValgrind()) {
177 return false; 207 return false;
178 } 208 }
179 209
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 CHECK_LE(0, proc_fd); 275 CHECK_LE(0, proc_fd);
246 276
247 CHECK(ChrootToSafeEmptyDir()); 277 CHECK(ChrootToSafeEmptyDir());
248 CHECK(!base::DirectoryExists(base::FilePath("/proc"))); 278 CHECK(!base::DirectoryExists(base::FilePath("/proc")));
249 CHECK(!ProcUtil::HasOpenDirectory(proc_fd)); 279 CHECK(!ProcUtil::HasOpenDirectory(proc_fd));
250 // We never let this function fail. 280 // We never let this function fail.
251 return true; 281 return true;
252 } 282 }
253 283
254 } // namespace sandbox. 284 } // namespace sandbox.
OLDNEW
« no previous file with comments | « sandbox/linux/services/credentials.h ('k') | sandbox/linux/services/credentials_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698