OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <fcntl.h> | 8 #include <fcntl.h> |
9 #include <stdio.h> | 9 #include <stdio.h> |
| 10 #include <sys/capability.h> |
10 #include <sys/stat.h> | 11 #include <sys/stat.h> |
11 #include <sys/types.h> | 12 #include <sys/types.h> |
12 #include <unistd.h> | 13 #include <unistd.h> |
13 | 14 |
| 15 #include <vector> |
| 16 |
14 #include "base/files/file_path.h" | 17 #include "base/files/file_path.h" |
15 #include "base/files/file_util.h" | 18 #include "base/files/file_util.h" |
16 #include "base/files/scoped_file.h" | 19 #include "base/files/scoped_file.h" |
17 #include "base/logging.h" | 20 #include "base/logging.h" |
18 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
19 #include "sandbox/linux/services/proc_util.h" | 22 #include "sandbox/linux/services/proc_util.h" |
| 23 #include "sandbox/linux/services/syscall_wrappers.h" |
| 24 #include "sandbox/linux/system_headers/capability.h" |
20 #include "sandbox/linux/tests/unit_tests.h" | 25 #include "sandbox/linux/tests/unit_tests.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
22 | 27 |
23 namespace sandbox { | 28 namespace sandbox { |
24 | 29 |
25 namespace { | 30 namespace { |
26 | 31 |
| 32 struct CapFreeDeleter { |
| 33 inline void operator()(cap_t cap) const { |
| 34 int ret = cap_free(cap); |
| 35 CHECK_EQ(0, ret); |
| 36 } |
| 37 }; |
| 38 |
| 39 // Wrapper to manage libcap2's cap_t type. |
| 40 typedef scoped_ptr<typeof(*((cap_t)0)), CapFreeDeleter> ScopedCap; |
| 41 |
27 bool WorkingDirectoryIsRoot() { | 42 bool WorkingDirectoryIsRoot() { |
28 char current_dir[PATH_MAX]; | 43 char current_dir[PATH_MAX]; |
29 char* cwd = getcwd(current_dir, sizeof(current_dir)); | 44 char* cwd = getcwd(current_dir, sizeof(current_dir)); |
30 PCHECK(cwd); | 45 PCHECK(cwd); |
31 if (strcmp("/", cwd)) return false; | 46 if (strcmp("/", cwd)) return false; |
32 | 47 |
33 // The current directory is the root. Add a few paranoid checks. | 48 // The current directory is the root. Add a few paranoid checks. |
34 struct stat current; | 49 struct stat current; |
35 CHECK_EQ(0, stat(".", ¤t)); | 50 CHECK_EQ(0, stat(".", ¤t)); |
36 struct stat parrent; | 51 struct stat parrent; |
37 CHECK_EQ(0, stat("..", &parrent)); | 52 CHECK_EQ(0, stat("..", &parrent)); |
38 CHECK_EQ(current.st_dev, parrent.st_dev); | 53 CHECK_EQ(current.st_dev, parrent.st_dev); |
39 CHECK_EQ(current.st_ino, parrent.st_ino); | 54 CHECK_EQ(current.st_ino, parrent.st_ino); |
40 CHECK_EQ(current.st_mode, parrent.st_mode); | 55 CHECK_EQ(current.st_mode, parrent.st_mode); |
41 CHECK_EQ(current.st_uid, parrent.st_uid); | 56 CHECK_EQ(current.st_uid, parrent.st_uid); |
42 CHECK_EQ(current.st_gid, parrent.st_gid); | 57 CHECK_EQ(current.st_gid, parrent.st_gid); |
43 return true; | 58 return true; |
44 } | 59 } |
45 | 60 |
46 SANDBOX_TEST(Credentials, DropAllCaps) { | 61 SANDBOX_TEST(Credentials, DropAllCaps) { |
47 CHECK(Credentials::DropAllCapabilities()); | 62 CHECK(Credentials::DropAllCapabilities()); |
48 CHECK(!Credentials::HasAnyCapability()); | 63 CHECK(!Credentials::HasAnyCapability()); |
49 } | 64 } |
50 | 65 |
51 SANDBOX_TEST(Credentials, GetCurrentCapString) { | |
52 CHECK(Credentials::DropAllCapabilities()); | |
53 const char kNoCapabilityText[] = "="; | |
54 CHECK(*Credentials::GetCurrentCapString() == kNoCapabilityText); | |
55 } | |
56 | |
57 SANDBOX_TEST(Credentials, MoveToNewUserNS) { | 66 SANDBOX_TEST(Credentials, MoveToNewUserNS) { |
58 CHECK(Credentials::DropAllCapabilities()); | 67 CHECK(Credentials::DropAllCapabilities()); |
59 bool moved_to_new_ns = Credentials::MoveToNewUserNS(); | 68 bool moved_to_new_ns = Credentials::MoveToNewUserNS(); |
60 fprintf(stdout, | 69 fprintf(stdout, |
61 "Unprivileged CLONE_NEWUSER supported: %s\n", | 70 "Unprivileged CLONE_NEWUSER supported: %s\n", |
62 moved_to_new_ns ? "true." : "false."); | 71 moved_to_new_ns ? "true." : "false."); |
63 fflush(stdout); | 72 fflush(stdout); |
64 if (!moved_to_new_ns) { | 73 if (!moved_to_new_ns) { |
65 fprintf(stdout, "This kernel does not support unprivileged namespaces. " | 74 fprintf(stdout, "This kernel does not support unprivileged namespaces. " |
66 "USERNS tests will succeed without running.\n"); | 75 "USERNS tests will succeed without running.\n"); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 if (!Credentials::MoveToNewUserNS()) return; | 163 if (!Credentials::MoveToNewUserNS()) return; |
155 CHECK(Credentials::DropFileSystemAccess(proc_fd.get())); | 164 CHECK(Credentials::DropFileSystemAccess(proc_fd.get())); |
156 CHECK(Credentials::DropAllCapabilities(proc_fd.get())); | 165 CHECK(Credentials::DropAllCapabilities(proc_fd.get())); |
157 | 166 |
158 // The kernel should now prevent us from regaining capabilities because we | 167 // The kernel should now prevent us from regaining capabilities because we |
159 // are in a chroot. | 168 // are in a chroot. |
160 CHECK(!Credentials::CanCreateProcessInNewUserNS()); | 169 CHECK(!Credentials::CanCreateProcessInNewUserNS()); |
161 CHECK(!Credentials::MoveToNewUserNS()); | 170 CHECK(!Credentials::MoveToNewUserNS()); |
162 } | 171 } |
163 | 172 |
| 173 SANDBOX_TEST(Credentials, SetCapabilities) { |
| 174 // Probably missing kernel support. |
| 175 if (!Credentials::MoveToNewUserNS()) |
| 176 return; |
| 177 |
| 178 base::ScopedFD proc_fd(ProcUtil::OpenProc()); |
| 179 |
| 180 CHECK(Credentials::HasCapability(LinuxCapability::kCapSysAdmin)); |
| 181 CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot)); |
| 182 |
| 183 const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot}; |
| 184 CHECK(Credentials::SetCapabilities(proc_fd.get(), caps)); |
| 185 |
| 186 CHECK(!Credentials::HasCapability(LinuxCapability::kCapSysAdmin)); |
| 187 CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot)); |
| 188 |
| 189 const std::vector<LinuxCapability> no_caps; |
| 190 CHECK(Credentials::SetCapabilities(proc_fd.get(), no_caps)); |
| 191 CHECK(!Credentials::HasAnyCapability()); |
| 192 } |
| 193 |
| 194 SANDBOX_TEST(Credentials, SetCapabilitiesAndChroot) { |
| 195 // Probably missing kernel support. |
| 196 if (!Credentials::MoveToNewUserNS()) |
| 197 return; |
| 198 |
| 199 base::ScopedFD proc_fd(ProcUtil::OpenProc()); |
| 200 |
| 201 CHECK(Credentials::HasCapability(LinuxCapability::kCapSysChroot)); |
| 202 PCHECK(chroot("/") == 0); |
| 203 |
| 204 const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot}; |
| 205 CHECK(Credentials::SetCapabilities(proc_fd.get(), caps)); |
| 206 PCHECK(chroot("/") == 0); |
| 207 |
| 208 CHECK(Credentials::DropAllCapabilities()); |
| 209 PCHECK(chroot("/") == -1 && errno == EPERM); |
| 210 } |
| 211 |
| 212 SANDBOX_TEST(Credentials, SetCapabilitiesMatchesLibCap2) { |
| 213 // Probably missing kernel support. |
| 214 if (!Credentials::MoveToNewUserNS()) |
| 215 return; |
| 216 |
| 217 base::ScopedFD proc_fd(ProcUtil::OpenProc()); |
| 218 |
| 219 const std::vector<LinuxCapability> caps = {LinuxCapability::kCapSysChroot}; |
| 220 CHECK(Credentials::SetCapabilities(proc_fd.get(), caps)); |
| 221 |
| 222 ScopedCap actual_cap(cap_get_proc()); |
| 223 PCHECK(actual_cap != nullptr); |
| 224 |
| 225 ScopedCap expected_cap(cap_init()); |
| 226 PCHECK(expected_cap != nullptr); |
| 227 |
| 228 const cap_value_t allowed_cap = CAP_SYS_CHROOT; |
| 229 for (const cap_flag_t flag : {CAP_EFFECTIVE, CAP_PERMITTED}) { |
| 230 PCHECK(cap_set_flag(expected_cap.get(), flag, 1, &allowed_cap, CAP_SET) == |
| 231 0); |
| 232 } |
| 233 |
| 234 CHECK_EQ(0, cap_compare(expected_cap.get(), actual_cap.get())); |
| 235 } |
| 236 |
164 } // namespace. | 237 } // namespace. |
165 | 238 |
166 } // namespace sandbox. | 239 } // namespace sandbox. |
OLD | NEW |