Fix clank compilation errors in the relocation_packer.
[chromium-blink-merge.git] / sandbox / linux / services / broker_process_unittest.cc
blob63535cb1a2e9bd4c2cbe4a8c73a1d4867cb34547
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/broker_process.h"
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sys/resource.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13 #include <unistd.h>
15 #include <algorithm>
16 #include <string>
17 #include <vector>
19 #include "base/basictypes.h"
20 #include "base/bind.h"
21 #include "base/file_util.h"
22 #include "base/files/scoped_file.h"
23 #include "base/logging.h"
24 #include "base/memory/scoped_ptr.h"
25 #include "base/posix/eintr_wrapper.h"
26 #include "base/posix/unix_domain_socket_linux.h"
27 #include "sandbox/linux/tests/scoped_temporary_file.h"
28 #include "sandbox/linux/tests/test_utils.h"
29 #include "sandbox/linux/tests/unit_tests.h"
30 #include "testing/gtest/include/gtest/gtest.h"
32 namespace sandbox {
34 class BrokerProcessTestHelper {
35 public:
36 static int get_ipc_socketpair(const BrokerProcess* broker) {
37 return broker->ipc_socketpair_;
41 namespace {
43 bool NoOpCallback() { return true; }
45 } // namespace
47 TEST(BrokerProcess, CreateAndDestroy) {
48 std::vector<std::string> read_whitelist;
49 read_whitelist.push_back("/proc/cpuinfo");
51 scoped_ptr<BrokerProcess> open_broker(
52 new BrokerProcess(EPERM, read_whitelist, std::vector<std::string>()));
53 ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
55 ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
56 // Destroy the broker and check it has exited properly.
57 open_broker.reset();
58 ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
61 TEST(BrokerProcess, TestOpenAccessNull) {
62 const std::vector<std::string> empty;
63 BrokerProcess open_broker(EPERM, empty, empty);
64 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
66 int fd = open_broker.Open(NULL, O_RDONLY);
67 ASSERT_EQ(fd, -EFAULT);
69 int ret = open_broker.Access(NULL, F_OK);
70 ASSERT_EQ(ret, -EFAULT);
73 void TestOpenFilePerms(bool fast_check_in_client, int denied_errno) {
74 const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1";
75 // We can't debug the init process, and shouldn't be able to access
76 // its auxv file.
77 const char kR_WhiteListedButDenied[] = "/proc/1/auxv";
78 const char kW_WhiteListed[] = "/proc/DOESNOTEXIST2";
79 const char kRW_WhiteListed[] = "/proc/DOESNOTEXIST3";
80 const char k_NotWhitelisted[] = "/proc/DOESNOTEXIST4";
82 std::vector<std::string> read_whitelist;
83 read_whitelist.push_back(kR_WhiteListed);
84 read_whitelist.push_back(kR_WhiteListedButDenied);
85 read_whitelist.push_back(kRW_WhiteListed);
87 std::vector<std::string> write_whitelist;
88 write_whitelist.push_back(kW_WhiteListed);
89 write_whitelist.push_back(kRW_WhiteListed);
91 BrokerProcess open_broker(denied_errno,
92 read_whitelist,
93 write_whitelist,
94 fast_check_in_client);
95 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
97 int fd = -1;
98 fd = open_broker.Open(kR_WhiteListed, O_RDONLY);
99 ASSERT_EQ(fd, -ENOENT);
100 fd = open_broker.Open(kR_WhiteListed, O_WRONLY);
101 ASSERT_EQ(fd, -denied_errno);
102 fd = open_broker.Open(kR_WhiteListed, O_RDWR);
103 ASSERT_EQ(fd, -denied_errno);
104 int ret = -1;
105 ret = open_broker.Access(kR_WhiteListed, F_OK);
106 ASSERT_EQ(ret, -ENOENT);
107 ret = open_broker.Access(kR_WhiteListed, R_OK);
108 ASSERT_EQ(ret, -ENOENT);
109 ret = open_broker.Access(kR_WhiteListed, W_OK);
110 ASSERT_EQ(ret, -denied_errno);
111 ret = open_broker.Access(kR_WhiteListed, R_OK | W_OK);
112 ASSERT_EQ(ret, -denied_errno);
113 ret = open_broker.Access(kR_WhiteListed, X_OK);
114 ASSERT_EQ(ret, -denied_errno);
115 ret = open_broker.Access(kR_WhiteListed, R_OK | X_OK);
116 ASSERT_EQ(ret, -denied_errno);
118 // Android sometimes runs tests as root.
119 // This part of the test requires a process that doesn't have
120 // CAP_DAC_OVERRIDE. We check against a root euid as a proxy for that.
121 if (geteuid()) {
122 fd = open_broker.Open(kR_WhiteListedButDenied, O_RDONLY);
123 // The broker process will allow this, but the normal permission system
124 // won't.
125 ASSERT_EQ(fd, -EACCES);
126 fd = open_broker.Open(kR_WhiteListedButDenied, O_WRONLY);
127 ASSERT_EQ(fd, -denied_errno);
128 fd = open_broker.Open(kR_WhiteListedButDenied, O_RDWR);
129 ASSERT_EQ(fd, -denied_errno);
130 ret = open_broker.Access(kR_WhiteListedButDenied, F_OK);
131 // The normal permission system will let us check that the file exists.
132 ASSERT_EQ(ret, 0);
133 ret = open_broker.Access(kR_WhiteListedButDenied, R_OK);
134 ASSERT_EQ(ret, -EACCES);
135 ret = open_broker.Access(kR_WhiteListedButDenied, W_OK);
136 ASSERT_EQ(ret, -denied_errno);
137 ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | W_OK);
138 ASSERT_EQ(ret, -denied_errno);
139 ret = open_broker.Access(kR_WhiteListedButDenied, X_OK);
140 ASSERT_EQ(ret, -denied_errno);
141 ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | X_OK);
142 ASSERT_EQ(ret, -denied_errno);
145 fd = open_broker.Open(kW_WhiteListed, O_RDONLY);
146 ASSERT_EQ(fd, -denied_errno);
147 fd = open_broker.Open(kW_WhiteListed, O_WRONLY);
148 ASSERT_EQ(fd, -ENOENT);
149 fd = open_broker.Open(kW_WhiteListed, O_RDWR);
150 ASSERT_EQ(fd, -denied_errno);
151 ret = open_broker.Access(kW_WhiteListed, F_OK);
152 ASSERT_EQ(ret, -ENOENT);
153 ret = open_broker.Access(kW_WhiteListed, R_OK);
154 ASSERT_EQ(ret, -denied_errno);
155 ret = open_broker.Access(kW_WhiteListed, W_OK);
156 ASSERT_EQ(ret, -ENOENT);
157 ret = open_broker.Access(kW_WhiteListed, R_OK | W_OK);
158 ASSERT_EQ(ret, -denied_errno);
159 ret = open_broker.Access(kW_WhiteListed, X_OK);
160 ASSERT_EQ(ret, -denied_errno);
161 ret = open_broker.Access(kW_WhiteListed, R_OK | X_OK);
162 ASSERT_EQ(ret, -denied_errno);
164 fd = open_broker.Open(kRW_WhiteListed, O_RDONLY);
165 ASSERT_EQ(fd, -ENOENT);
166 fd = open_broker.Open(kRW_WhiteListed, O_WRONLY);
167 ASSERT_EQ(fd, -ENOENT);
168 fd = open_broker.Open(kRW_WhiteListed, O_RDWR);
169 ASSERT_EQ(fd, -ENOENT);
170 ret = open_broker.Access(kRW_WhiteListed, F_OK);
171 ASSERT_EQ(ret, -ENOENT);
172 ret = open_broker.Access(kRW_WhiteListed, R_OK);
173 ASSERT_EQ(ret, -ENOENT);
174 ret = open_broker.Access(kRW_WhiteListed, W_OK);
175 ASSERT_EQ(ret, -ENOENT);
176 ret = open_broker.Access(kRW_WhiteListed, R_OK | W_OK);
177 ASSERT_EQ(ret, -ENOENT);
178 ret = open_broker.Access(kRW_WhiteListed, X_OK);
179 ASSERT_EQ(ret, -denied_errno);
180 ret = open_broker.Access(kRW_WhiteListed, R_OK | X_OK);
181 ASSERT_EQ(ret, -denied_errno);
183 fd = open_broker.Open(k_NotWhitelisted, O_RDONLY);
184 ASSERT_EQ(fd, -denied_errno);
185 fd = open_broker.Open(k_NotWhitelisted, O_WRONLY);
186 ASSERT_EQ(fd, -denied_errno);
187 fd = open_broker.Open(k_NotWhitelisted, O_RDWR);
188 ASSERT_EQ(fd, -denied_errno);
189 ret = open_broker.Access(k_NotWhitelisted, F_OK);
190 ASSERT_EQ(ret, -denied_errno);
191 ret = open_broker.Access(k_NotWhitelisted, R_OK);
192 ASSERT_EQ(ret, -denied_errno);
193 ret = open_broker.Access(k_NotWhitelisted, W_OK);
194 ASSERT_EQ(ret, -denied_errno);
195 ret = open_broker.Access(k_NotWhitelisted, R_OK | W_OK);
196 ASSERT_EQ(ret, -denied_errno);
197 ret = open_broker.Access(k_NotWhitelisted, X_OK);
198 ASSERT_EQ(ret, -denied_errno);
199 ret = open_broker.Access(k_NotWhitelisted, R_OK | X_OK);
200 ASSERT_EQ(ret, -denied_errno);
202 // We have some extra sanity check for clearly wrong values.
203 fd = open_broker.Open(kRW_WhiteListed, O_RDONLY | O_WRONLY | O_RDWR);
204 ASSERT_EQ(fd, -denied_errno);
206 // It makes no sense to allow O_CREAT in a 2-parameters open. Ensure this
207 // is denied.
208 fd = open_broker.Open(kRW_WhiteListed, O_RDWR | O_CREAT);
209 ASSERT_EQ(fd, -denied_errno);
212 // Run the same thing twice. The second time, we make sure that no security
213 // check is performed on the client.
214 TEST(BrokerProcess, OpenFilePermsWithClientCheck) {
215 TestOpenFilePerms(true /* fast_check_in_client */, EPERM);
216 // Don't do anything here, so that ASSERT works in the subfunction as
217 // expected.
220 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheck) {
221 TestOpenFilePerms(false /* fast_check_in_client */, EPERM);
222 // Don't do anything here, so that ASSERT works in the subfunction as
223 // expected.
226 // Run the same twice again, but with ENOENT instead of EPERM.
227 TEST(BrokerProcess, OpenFilePermsWithClientCheckNoEnt) {
228 TestOpenFilePerms(true /* fast_check_in_client */, ENOENT);
229 // Don't do anything here, so that ASSERT works in the subfunction as
230 // expected.
233 TEST(BrokerProcess, OpenOpenFilePermsNoClientCheckNoEnt) {
234 TestOpenFilePerms(false /* fast_check_in_client */, ENOENT);
235 // Don't do anything here, so that ASSERT works in the subfunction as
236 // expected.
239 void TestOpenCpuinfo(bool fast_check_in_client) {
240 const char kFileCpuInfo[] = "/proc/cpuinfo";
241 std::vector<std::string> read_whitelist;
242 read_whitelist.push_back(kFileCpuInfo);
244 scoped_ptr<BrokerProcess> open_broker(new BrokerProcess(
245 EPERM, read_whitelist, std::vector<std::string>(), fast_check_in_client));
246 ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
248 int fd = -1;
249 fd = open_broker->Open(kFileCpuInfo, O_RDWR);
250 base::ScopedFD fd_closer(fd);
251 ASSERT_EQ(fd, -EPERM);
253 // Check we can read /proc/cpuinfo.
254 int can_access = open_broker->Access(kFileCpuInfo, R_OK);
255 ASSERT_EQ(can_access, 0);
256 can_access = open_broker->Access(kFileCpuInfo, W_OK);
257 ASSERT_EQ(can_access, -EPERM);
258 // Check we can not write /proc/cpuinfo.
260 // Open cpuinfo via the broker.
261 int cpuinfo_fd = open_broker->Open(kFileCpuInfo, O_RDONLY);
262 base::ScopedFD cpuinfo_fd_closer(cpuinfo_fd);
263 ASSERT_GE(cpuinfo_fd, 0);
264 char buf[3];
265 memset(buf, 0, sizeof(buf));
266 int read_len1 = read(cpuinfo_fd, buf, sizeof(buf));
267 ASSERT_GT(read_len1, 0);
269 // Open cpuinfo directly.
270 int cpuinfo_fd2 = open(kFileCpuInfo, O_RDONLY);
271 base::ScopedFD cpuinfo_fd2_closer(cpuinfo_fd2);
272 ASSERT_GE(cpuinfo_fd2, 0);
273 char buf2[3];
274 memset(buf2, 1, sizeof(buf2));
275 int read_len2 = read(cpuinfo_fd2, buf2, sizeof(buf2));
276 ASSERT_GT(read_len1, 0);
278 // The following is not guaranteed true, but will be in practice.
279 ASSERT_EQ(read_len1, read_len2);
280 // Compare the cpuinfo as returned by the broker with the one we opened
281 // ourselves.
282 ASSERT_EQ(memcmp(buf, buf2, read_len1), 0);
284 ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
285 open_broker.reset();
286 ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
289 // Run the same thing twice. The second time, we make sure that no security
290 // check is performed on the client.
291 TEST(BrokerProcess, OpenCpuinfoWithClientCheck) {
292 TestOpenCpuinfo(true /* fast_check_in_client */);
293 // Don't do anything here, so that ASSERT works in the subfunction as
294 // expected.
297 TEST(BrokerProcess, OpenCpuinfoNoClientCheck) {
298 TestOpenCpuinfo(false /* fast_check_in_client */);
299 // Don't do anything here, so that ASSERT works in the subfunction as
300 // expected.
303 TEST(BrokerProcess, OpenFileRW) {
304 ScopedTemporaryFile tempfile;
305 const char* tempfile_name = tempfile.full_file_name();
307 std::vector<std::string> whitelist;
308 whitelist.push_back(tempfile_name);
310 BrokerProcess open_broker(EPERM, whitelist, whitelist);
311 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
313 // Check we can access that file with read or write.
314 int can_access = open_broker.Access(tempfile_name, R_OK | W_OK);
315 ASSERT_EQ(can_access, 0);
317 int tempfile2 = -1;
318 tempfile2 = open_broker.Open(tempfile_name, O_RDWR);
319 ASSERT_GE(tempfile2, 0);
321 // Write to the descriptor opened by the broker.
322 char test_text[] = "TESTTESTTEST";
323 ssize_t len = write(tempfile2, test_text, sizeof(test_text));
324 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
326 // Read back from the original file descriptor what we wrote through
327 // the descriptor provided by the broker.
328 char buf[1024];
329 len = read(tempfile.fd(), buf, sizeof(buf));
331 ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
332 ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0);
334 ASSERT_EQ(close(tempfile2), 0);
337 // SANDBOX_TEST because the process could die with a SIGPIPE
338 // and we want this to happen in a subprocess.
339 SANDBOX_TEST(BrokerProcess, BrokerDied) {
340 std::vector<std::string> read_whitelist;
341 read_whitelist.push_back("/proc/cpuinfo");
343 BrokerProcess open_broker(EPERM,
344 read_whitelist,
345 std::vector<std::string>(),
346 true /* fast_check_in_client */,
347 true /* quiet_failures_for_tests */);
348 SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
349 const pid_t broker_pid = open_broker.broker_pid();
350 SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0);
352 // Now we check that the broker has been signaled, but do not reap it.
353 siginfo_t process_info;
354 SANDBOX_ASSERT(HANDLE_EINTR(waitid(
355 P_PID, broker_pid, &process_info, WEXITED | WNOWAIT)) ==
357 SANDBOX_ASSERT(broker_pid == process_info.si_pid);
358 SANDBOX_ASSERT(CLD_KILLED == process_info.si_code);
359 SANDBOX_ASSERT(SIGKILL == process_info.si_status);
361 // Check that doing Open with a dead broker won't SIGPIPE us.
362 SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
363 SANDBOX_ASSERT(open_broker.Access("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
366 void TestOpenComplexFlags(bool fast_check_in_client) {
367 const char kCpuInfo[] = "/proc/cpuinfo";
368 std::vector<std::string> whitelist;
369 whitelist.push_back(kCpuInfo);
371 BrokerProcess open_broker(EPERM,
372 whitelist,
373 whitelist,
374 fast_check_in_client);
375 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
376 // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK.
377 int fd = -1;
378 int ret = 0;
379 fd = open_broker.Open(kCpuInfo, O_RDONLY);
380 ASSERT_GE(fd, 0);
381 ret = fcntl(fd, F_GETFL);
382 ASSERT_NE(-1, ret);
383 // The descriptor shouldn't have the O_CLOEXEC attribute, nor O_NONBLOCK.
384 ASSERT_EQ(0, ret & (O_CLOEXEC | O_NONBLOCK));
385 ASSERT_EQ(0, close(fd));
387 fd = open_broker.Open(kCpuInfo, O_RDONLY | O_CLOEXEC);
388 ASSERT_GE(fd, 0);
389 ret = fcntl(fd, F_GETFD);
390 ASSERT_NE(-1, ret);
391 // Important: use F_GETFD, not F_GETFL. The O_CLOEXEC flag in F_GETFL
392 // is actually not used by the kernel.
393 ASSERT_TRUE(FD_CLOEXEC & ret);
394 ASSERT_EQ(0, close(fd));
396 fd = open_broker.Open(kCpuInfo, O_RDONLY | O_NONBLOCK);
397 ASSERT_GE(fd, 0);
398 ret = fcntl(fd, F_GETFL);
399 ASSERT_NE(-1, ret);
400 ASSERT_TRUE(O_NONBLOCK & ret);
401 ASSERT_EQ(0, close(fd));
404 TEST(BrokerProcess, OpenComplexFlagsWithClientCheck) {
405 TestOpenComplexFlags(true /* fast_check_in_client */);
406 // Don't do anything here, so that ASSERT works in the subfunction as
407 // expected.
410 TEST(BrokerProcess, OpenComplexFlagsNoClientCheck) {
411 TestOpenComplexFlags(false /* fast_check_in_client */);
412 // Don't do anything here, so that ASSERT works in the subfunction as
413 // expected.
416 // We need to allow noise because the broker will log when it receives our
417 // bogus IPCs.
418 SANDBOX_TEST_ALLOW_NOISE(BrokerProcess, RecvMsgDescriptorLeak) {
419 // Find the four lowest available file descriptors.
420 int available_fds[4];
421 SANDBOX_ASSERT(0 == pipe(available_fds));
422 SANDBOX_ASSERT(0 == pipe(available_fds + 2));
424 // Save one FD to send to the broker later, and close the others.
425 base::ScopedFD message_fd(available_fds[0]);
426 for (size_t i = 1; i < arraysize(available_fds); i++) {
427 SANDBOX_ASSERT(0 == IGNORE_EINTR(close(available_fds[i])));
430 // Lower our file descriptor limit to just allow three more file descriptors
431 // to be allocated. (N.B., RLIMIT_NOFILE doesn't limit the number of file
432 // descriptors a process can have: it only limits the highest value that can
433 // be assigned to newly-created descriptors allocated by the process.)
434 const rlim_t fd_limit =
435 1 + *std::max_element(available_fds,
436 available_fds + arraysize(available_fds));
438 // Valgrind doesn't allow changing the hard descriptor limit, so we only
439 // change the soft descriptor limit here.
440 struct rlimit rlim;
441 SANDBOX_ASSERT(0 == getrlimit(RLIMIT_NOFILE, &rlim));
442 SANDBOX_ASSERT(fd_limit <= rlim.rlim_cur);
443 rlim.rlim_cur = fd_limit;
444 SANDBOX_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &rlim));
446 static const char kCpuInfo[] = "/proc/cpuinfo";
447 std::vector<std::string> read_whitelist;
448 read_whitelist.push_back(kCpuInfo);
450 BrokerProcess open_broker(EPERM, read_whitelist, std::vector<std::string>());
451 SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
453 const int ipc_fd = BrokerProcessTestHelper::get_ipc_socketpair(&open_broker);
454 SANDBOX_ASSERT(ipc_fd >= 0);
456 static const char kBogus[] = "not a pickle";
457 std::vector<int> fds;
458 fds.push_back(message_fd.get());
460 // The broker process should only have a couple spare file descriptors
461 // available, but for good measure we send it fd_limit bogus IPCs anyway.
462 for (rlim_t i = 0; i < fd_limit; ++i) {
463 SANDBOX_ASSERT(
464 UnixDomainSocket::SendMsg(ipc_fd, kBogus, sizeof(kBogus), fds));
467 const int fd = open_broker.Open(kCpuInfo, O_RDONLY);
468 SANDBOX_ASSERT(fd >= 0);
469 SANDBOX_ASSERT(0 == IGNORE_EINTR(close(fd)));
472 } // namespace sandbox