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

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

Issue 11557025: Linux sandbox: add a new low-level broker process mechanism. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add copyright notice Created 8 years 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 | Annotate | Revision Log
« no previous file with comments | « sandbox/linux/services/broker_process.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "sandbox/linux/services/broker_process.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <sys/wait.h>
12 #include <string>
13 #include <vector>
14
15 #include "base/logging.h"
16 #include "sandbox/linux/tests/unit_tests.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace sandbox {
20
21 TEST(BrokerProcess, CreateAndDestroy) {
22 std::vector<std::string> read_whitelist;
23 read_whitelist.push_back("/proc/cpuinfo");
24
25 BrokerProcess* open_broker = new BrokerProcess(read_whitelist,
26 std::vector<std::string>());
27 ASSERT_TRUE(open_broker->Init(NULL));
28 pid_t broker_pid = open_broker->broker_pid();
29 delete(open_broker);
30
31 // Now we check that the broker has exited properly.
32 int status = 0;
33 EXPECT_EQ(waitpid(broker_pid, &status, 0), broker_pid);
34 EXPECT_TRUE(WIFEXITED(status));
35 EXPECT_EQ(WEXITSTATUS(status), 0);
36 }
37
38 TEST(BrokerProcess, TestOpenNull) {
39 const std::vector<std::string> empty;
40 BrokerProcess open_broker(empty, empty);
41 ASSERT_TRUE(open_broker.Init(NULL));
42
43 int fd = open_broker.Open(NULL, O_RDONLY);
44 EXPECT_EQ(fd, -EFAULT);
45 }
46
47 void TestOpenFilePerms(bool fast_check_in_client) {
48 const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1";
49 const char kW_WhiteListed[] = "/proc/DOESNOTEXIST2";
50 const char kRW_WhiteListed[] = "/proc/DOESNOTEXIST3";
51 const char k_NotWhitelisted[] = "/proc/DOESNOTEXIST4";
52
53 std::vector<std::string> read_whitelist;
54 read_whitelist.push_back(kR_WhiteListed);
55 read_whitelist.push_back(kRW_WhiteListed);
56
57 std::vector<std::string> write_whitelist;
58 write_whitelist.push_back(kW_WhiteListed);
59 write_whitelist.push_back(kRW_WhiteListed);
60
61 BrokerProcess open_broker(read_whitelist,
62 write_whitelist,
63 fast_check_in_client);
64 ASSERT_TRUE(open_broker.Init(NULL));
65
66 int fd = -1;
67 fd = open_broker.Open(kR_WhiteListed, O_RDONLY);
68 EXPECT_EQ(fd, -ENOENT);
69 fd = open_broker.Open(kR_WhiteListed, O_WRONLY);
70 EXPECT_EQ(fd, -EPERM);
71 fd = open_broker.Open(kR_WhiteListed, O_RDWR);
72 EXPECT_EQ(fd, -EPERM);
73
74 fd = open_broker.Open(kW_WhiteListed, O_RDONLY);
75 EXPECT_EQ(fd, -EPERM);
76 fd = open_broker.Open(kW_WhiteListed, O_WRONLY);
77 EXPECT_EQ(fd, -ENOENT);
78 fd = open_broker.Open(kW_WhiteListed, O_RDWR);
79 EXPECT_EQ(fd, -EPERM);
80
81 fd = open_broker.Open(kRW_WhiteListed, O_RDONLY);
82 EXPECT_EQ(fd, -ENOENT);
83 fd = open_broker.Open(kRW_WhiteListed, O_WRONLY);
84 EXPECT_EQ(fd, -ENOENT);
85 fd = open_broker.Open(kRW_WhiteListed, O_RDWR);
86 EXPECT_EQ(fd, -ENOENT);
87
88 fd = open_broker.Open(k_NotWhitelisted, O_RDONLY);
89 EXPECT_EQ(fd, -EPERM);
90 fd = open_broker.Open(k_NotWhitelisted, O_WRONLY);
91 EXPECT_EQ(fd, -EPERM);
92 fd = open_broker.Open(k_NotWhitelisted, O_RDWR);
93 EXPECT_EQ(fd, -EPERM);
94
95 // We have some extra sanity check for clearly wrong values.
96 fd = open_broker.Open(kRW_WhiteListed, O_RDONLY|O_WRONLY|O_RDWR);
97 EXPECT_EQ(fd, -EPERM);
98 }
99
100 // Run the same thing twice. The second time, we make sure that no security
101 // check is performed on the client.
102 TEST(BrokerProcess, OpenFilePermsWithClientCheck) {
103 TestOpenFilePerms(true /* fast_check_in_client */);
104 }
105
106 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheck) {
107 TestOpenFilePerms(false /* fast_check_in_client */);
108 }
109
110
111 void TestOpenCpuinfo(bool fast_check_in_client) {
112 const char kFileCpuInfo[] = "/proc/cpuinfo";
113 std::vector<std::string> read_whitelist;
114 read_whitelist.push_back(kFileCpuInfo);
115
116 BrokerProcess* open_broker = new BrokerProcess(read_whitelist,
117 std::vector<std::string>(),
118 fast_check_in_client);
119 ASSERT_TRUE(open_broker->Init(NULL));
120 pid_t broker_pid = open_broker->broker_pid();
121
122 int fd = -1;
123 fd = open_broker->Open(kFileCpuInfo, O_RDWR);
124 EXPECT_EQ(fd, -EPERM);
125
126 // Open cpuinfo via the broker.
127 int cpuinfo_fd = open_broker->Open(kFileCpuInfo, O_RDONLY);
128 ASSERT_GE(cpuinfo_fd, 0);
129 char buf[3];
130 memset(buf, 0, sizeof(buf));
131 int read_len1 = read(cpuinfo_fd, buf, sizeof(buf));
132 EXPECT_GT(read_len1, 0);
133
134 // Open cpuinfo directly.
135 int cpuinfo_fd2 = open(kFileCpuInfo, O_RDONLY);
136 ASSERT_GE(cpuinfo_fd2, 0);
137 char buf2[3];
138 memset(buf2, 1, sizeof(buf2));
139 int read_len2 = read(cpuinfo_fd2, buf2, sizeof(buf2));
140 EXPECT_GT(read_len1, 0);
141
142 // The following is not guaranteed true, but will be in practice.
143 EXPECT_EQ(read_len1, read_len2);
144 // Compare the cpuinfo as returned by the broker with the one we opened
145 // ourselves.
146 EXPECT_EQ(memcmp(buf, buf2, read_len1), 0);
147
148 if (fd >= 0)
149 close(fd);
150 if (cpuinfo_fd >= 0)
151 close(cpuinfo_fd);
152 if (cpuinfo_fd2 >= 0)
153 close(cpuinfo_fd);
154
155 delete(open_broker);
156
157 // Now we check that the broker has exited properly.
158 int status = 0;
159 EXPECT_EQ(waitpid(broker_pid, &status, 0), broker_pid);
160 EXPECT_TRUE(WIFEXITED(status));
161 EXPECT_EQ(WEXITSTATUS(status), 0);
162 }
163
164 // Run the same thing twice. The second time, we make sure that no security
165 // check is performed on the client.
166 TEST(BrokerProcess, OpenCpuinfoWithClientCheck) {
167 TestOpenCpuinfo(true /* fast_check_in_client */);
168 }
169
170 TEST(BrokerProcess, OpenCpuinfoNoClientCheck) {
171 TestOpenCpuinfo(false /* fast_check_in_client */);
172 }
173
174 TEST(BrokerProcess, OpenFileRW) {
175 char templatename[] = "BrokerProcessXXXXXX";
176 int tempfile = mkstemp(templatename);
177 ASSERT_GE(tempfile, 0);
178 char tempfile_name[2048];
179 int written = snprintf(tempfile_name, sizeof(tempfile_name),
180 "/proc/self/fd/%d", tempfile);
181 ASSERT_LT(written, static_cast<int>(sizeof(tempfile_name)));
182
183 std::vector<std::string> whitelist;
184 whitelist.push_back(tempfile_name);
185
186 BrokerProcess open_broker(whitelist, whitelist);
187 ASSERT_TRUE(open_broker.Init(NULL));
188
189 int tempfile2 = -1;
190 tempfile2 = open_broker.Open(tempfile_name, O_RDWR);
191 ASSERT_GE(tempfile2, 0);
192
193 // Write to the descriptor opened by the broker.
194 char test_text[] = "TESTTESTTEST";
195 ssize_t len = write(tempfile2, test_text, sizeof(test_text));
196 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
197
198 // Read back from the original file descriptor what we wrote through
199 // the descriptor provided by the broker.
200 char buf[1024];
201 len = read(tempfile, buf, sizeof(buf));
202
203 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
204 ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0);
205
206 // Cleanup the temporary file.
207 char tempfile_full_path[2048];
208 // Make sure tempfile_full_path will terminate with a 0.
209 memset(tempfile_full_path, 0, sizeof(tempfile_full_path));
210 ssize_t ret = readlink(tempfile_name, tempfile_full_path,
211 sizeof(tempfile_full_path));
212 ASSERT_GT(ret, 0);
213 // Make sure we still have a trailing zero in tempfile_full_path.
214 ASSERT_LT(ret, static_cast<ssize_t>(sizeof(tempfile_full_path)));
215 ASSERT_EQ(unlink(tempfile_full_path), 0);
216
217 EXPECT_EQ(close(tempfile), 0);
218 EXPECT_EQ(close(tempfile2), 0);
219 }
220
221 // Sandbox test because we could get a SIGPIPE.
222 SANDBOX_TEST(BrokerProcess, BrokerDied) {
223 std::vector<std::string> read_whitelist;
224 read_whitelist.push_back("/proc/cpuinfo");
225
226 BrokerProcess open_broker(read_whitelist,
227 std::vector<std::string>(),
228 true /* fast_check_in_client */,
229 true /* quiet_failures_for_tests */);
230 SANDBOX_ASSERT(open_broker.Init(NULL));
231 pid_t broker_pid = open_broker.broker_pid();
232 SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0);
233
234 // Now we check that the broker has exited properly.
235 int status = 0;
236 SANDBOX_ASSERT(waitpid(broker_pid, &status, 0) == broker_pid);
237 SANDBOX_ASSERT(WIFSIGNALED(status));
238 SANDBOX_ASSERT(WTERMSIG(status) == SIGKILL);
239 // Hopefully doing Open with a dead broker won't SIGPIPE us.
240 SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
241 }
242
243 void TestComplexFlags(bool fast_check_in_client) {
244 std::vector<std::string> whitelist;
245 whitelist.push_back("/proc/cpuinfo");
246
247 BrokerProcess open_broker(whitelist,
248 whitelist,
249 fast_check_in_client);
250 ASSERT_TRUE(open_broker.Init(NULL));
251 // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK.
252 // Presently, the right thing is to always deny them since they are not
253 // supported.
254 int fd = -1;
255 fd = open_broker.Open("/proc/cpuinfo", O_RDONLY);
256 ASSERT_GE(fd, 0);
257 ASSERT_EQ(close(fd), 0);
258
259 ASSERT_EQ(open_broker.Open("/proc/cpuinfo", O_RDONLY | O_CLOEXEC), -EPERM);
260 ASSERT_EQ(open_broker.Open("/proc/cpuinfo", O_RDONLY | O_NONBLOCK), -EPERM);
261 }
262
263 TEST(BrokerProcess, ComplexFlagsWithClientCheck) {
264 TestComplexFlags(true /* fast_check_in_client */);
265 }
266
267 TEST(BrokerProcess, ComplexFlagsNoClientCheck) {
268 TestComplexFlags(false /* fast_check_in_client */);
269 }
270
271 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/services/broker_process.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698