Fix crash on app list start page keyboard navigation with <4 apps.
[chromium-blink-merge.git] / sandbox / linux / services / credentials_unittest.cc
blob40a2bc45f7ebae0cac6890c0ddfb28e72d758e75
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
3 // found in the LICENSE file.
5 #include "sandbox/linux/services/credentials.h"
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <unistd.h>
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/files/scoped_file.h"
17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "sandbox/linux/tests/unit_tests.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 namespace sandbox {
24 namespace {
26 bool WorkingDirectoryIsRoot() {
27 char current_dir[PATH_MAX];
28 char* cwd = getcwd(current_dir, sizeof(current_dir));
29 PCHECK(cwd);
30 if (strcmp("/", cwd)) return false;
32 // The current directory is the root. Add a few paranoid checks.
33 struct stat current;
34 CHECK_EQ(0, stat(".", &current));
35 struct stat parrent;
36 CHECK_EQ(0, stat("..", &parrent));
37 CHECK_EQ(current.st_dev, parrent.st_dev);
38 CHECK_EQ(current.st_ino, parrent.st_ino);
39 CHECK_EQ(current.st_mode, parrent.st_mode);
40 CHECK_EQ(current.st_uid, parrent.st_uid);
41 CHECK_EQ(current.st_gid, parrent.st_gid);
42 return true;
45 SANDBOX_TEST(Credentials, DropAllCaps) {
46 CHECK(Credentials::DropAllCapabilities());
47 CHECK(!Credentials::HasAnyCapability());
50 SANDBOX_TEST(Credentials, GetCurrentCapString) {
51 CHECK(Credentials::DropAllCapabilities());
52 const char kNoCapabilityText[] = "=";
53 CHECK(*Credentials::GetCurrentCapString() == kNoCapabilityText);
56 SANDBOX_TEST(Credentials, MoveToNewUserNS) {
57 CHECK(Credentials::DropAllCapabilities());
58 bool moved_to_new_ns = Credentials::MoveToNewUserNS();
59 fprintf(stdout,
60 "Unprivileged CLONE_NEWUSER supported: %s\n",
61 moved_to_new_ns ? "true." : "false.");
62 fflush(stdout);
63 if (!moved_to_new_ns) {
64 fprintf(stdout, "This kernel does not support unprivileged namespaces. "
65 "USERNS tests will succeed without running.\n");
66 fflush(stdout);
67 return;
69 CHECK(Credentials::HasAnyCapability());
70 CHECK(Credentials::DropAllCapabilities());
71 CHECK(!Credentials::HasAnyCapability());
74 SANDBOX_TEST(Credentials, CanCreateProcessInNewUserNS) {
75 CHECK(Credentials::DropAllCapabilities());
76 bool user_ns_supported = Credentials::CanCreateProcessInNewUserNS();
77 bool moved_to_new_ns = Credentials::MoveToNewUserNS();
78 CHECK_EQ(user_ns_supported, moved_to_new_ns);
81 SANDBOX_TEST(Credentials, UidIsPreserved) {
82 CHECK(Credentials::DropAllCapabilities());
83 uid_t old_ruid, old_euid, old_suid;
84 gid_t old_rgid, old_egid, old_sgid;
85 PCHECK(0 == getresuid(&old_ruid, &old_euid, &old_suid));
86 PCHECK(0 == getresgid(&old_rgid, &old_egid, &old_sgid));
87 // Probably missing kernel support.
88 if (!Credentials::MoveToNewUserNS()) return;
89 uid_t new_ruid, new_euid, new_suid;
90 PCHECK(0 == getresuid(&new_ruid, &new_euid, &new_suid));
91 CHECK(old_ruid == new_ruid);
92 CHECK(old_euid == new_euid);
93 CHECK(old_suid == new_suid);
95 gid_t new_rgid, new_egid, new_sgid;
96 PCHECK(0 == getresgid(&new_rgid, &new_egid, &new_sgid));
97 CHECK(old_rgid == new_rgid);
98 CHECK(old_egid == new_egid);
99 CHECK(old_sgid == new_sgid);
102 bool NewUserNSCycle() {
103 if (!Credentials::MoveToNewUserNS() ||
104 !Credentials::HasAnyCapability() ||
105 !Credentials::DropAllCapabilities() ||
106 Credentials::HasAnyCapability()) {
107 return false;
109 return true;
112 SANDBOX_TEST(Credentials, NestedUserNS) {
113 CHECK(Credentials::DropAllCapabilities());
114 // Probably missing kernel support.
115 if (!Credentials::MoveToNewUserNS()) return;
116 CHECK(Credentials::DropAllCapabilities());
117 // As of 3.12, the kernel has a limit of 32. See create_user_ns().
118 const int kNestLevel = 10;
119 for (int i = 0; i < kNestLevel; ++i) {
120 CHECK(NewUserNSCycle()) << "Creating new user NS failed at iteration "
121 << i << ".";
125 // Test the WorkingDirectoryIsRoot() helper.
126 SANDBOX_TEST(Credentials, CanDetectRoot) {
127 PCHECK(0 == chdir("/proc/"));
128 CHECK(!WorkingDirectoryIsRoot());
129 PCHECK(0 == chdir("/"));
130 CHECK(WorkingDirectoryIsRoot());
133 // Disabled on ASAN because of crbug.com/451603.
134 SANDBOX_TEST(Credentials, DISABLE_ON_ASAN(DropFileSystemAccessIsSafe)) {
135 CHECK(Credentials::DropAllCapabilities());
136 // Probably missing kernel support.
137 if (!Credentials::MoveToNewUserNS()) return;
138 CHECK(Credentials::DropFileSystemAccess());
139 CHECK(!base::DirectoryExists(base::FilePath("/proc")));
140 CHECK(WorkingDirectoryIsRoot());
141 CHECK(base::IsDirectoryEmpty(base::FilePath("/")));
142 // We want the chroot to never have a subdirectory. A subdirectory
143 // could allow a chroot escape.
144 CHECK_NE(0, mkdir("/test", 0700));
147 // Check that after dropping filesystem access and dropping privileges
148 // it is not possible to regain capabilities.
149 SANDBOX_TEST(Credentials, DISABLE_ON_ASAN(CannotRegainPrivileges)) {
150 CHECK(Credentials::DropAllCapabilities());
151 // Probably missing kernel support.
152 if (!Credentials::MoveToNewUserNS()) return;
153 CHECK(Credentials::DropFileSystemAccess());
154 CHECK(Credentials::DropAllCapabilities());
156 // The kernel should now prevent us from regaining capabilities because we
157 // are in a chroot.
158 CHECK(!Credentials::CanCreateProcessInNewUserNS());
159 CHECK(!Credentials::MoveToNewUserNS());
162 } // namespace.
164 } // namespace sandbox.