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/broker_process.h" | 5 #include "sandbox/linux/services/broker_process.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
11 #include <sys/wait.h> | 11 #include <sys/wait.h> |
12 #include <unistd.h> | 12 #include <unistd.h> |
13 | 13 |
14 #include <string> | 14 #include <string> |
15 #include <vector> | 15 #include <vector> |
16 | 16 |
17 #include "base/basictypes.h" | 17 #include "base/basictypes.h" |
| 18 #include "base/bind.h" |
18 #include "base/file_util.h" | 19 #include "base/file_util.h" |
19 #include "base/logging.h" | 20 #include "base/logging.h" |
20 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
21 #include "base/posix/eintr_wrapper.h" | 22 #include "base/posix/eintr_wrapper.h" |
22 #include "sandbox/linux/tests/unit_tests.h" | 23 #include "sandbox/linux/tests/unit_tests.h" |
23 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
24 | 25 |
25 using file_util::ScopedFD; | 26 using file_util::ScopedFD; |
26 | 27 |
27 namespace sandbox { | 28 namespace sandbox { |
(...skipping 25 matching lines...) Expand all Loading... |
53 | 54 |
54 int fd() const { return fd_; } | 55 int fd() const { return fd_; } |
55 const char* full_file_name() const { return full_file_name_; } | 56 const char* full_file_name() const { return full_file_name_; } |
56 | 57 |
57 private: | 58 private: |
58 int fd_; | 59 int fd_; |
59 char full_file_name_[128]; | 60 char full_file_name_[128]; |
60 DISALLOW_COPY_AND_ASSIGN(ScopedTemporaryFile); | 61 DISALLOW_COPY_AND_ASSIGN(ScopedTemporaryFile); |
61 }; | 62 }; |
62 | 63 |
| 64 bool NoOpCallback() { |
| 65 return true; |
| 66 } |
| 67 |
63 } // namespace | 68 } // namespace |
64 | 69 |
65 #if defined(OS_ANDROID) | 70 #if defined(OS_ANDROID) |
66 #define DISABLE_ON_ANDROID(function) DISABLED_##function | 71 #define DISABLE_ON_ANDROID(function) DISABLED_##function |
67 #else | 72 #else |
68 #define DISABLE_ON_ANDROID(function) function | 73 #define DISABLE_ON_ANDROID(function) function |
69 #endif | 74 #endif |
70 | 75 |
71 TEST(BrokerProcess, CreateAndDestroy) { | 76 TEST(BrokerProcess, CreateAndDestroy) { |
72 std::vector<std::string> read_whitelist; | 77 std::vector<std::string> read_whitelist; |
73 read_whitelist.push_back("/proc/cpuinfo"); | 78 read_whitelist.push_back("/proc/cpuinfo"); |
74 | 79 |
75 scoped_ptr<BrokerProcess> open_broker( | 80 scoped_ptr<BrokerProcess> open_broker( |
76 new BrokerProcess(EPERM, read_whitelist, std::vector<std::string>())); | 81 new BrokerProcess(EPERM, read_whitelist, std::vector<std::string>())); |
77 ASSERT_TRUE(open_broker->Init(NULL)); | 82 ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback))); |
78 pid_t broker_pid = open_broker->broker_pid(); | 83 pid_t broker_pid = open_broker->broker_pid(); |
79 | 84 |
80 // Destroy the broker and check it has exited properly. | 85 // Destroy the broker and check it has exited properly. |
81 open_broker.reset(); | 86 open_broker.reset(); |
82 int status = 0; | 87 int status = 0; |
83 ASSERT_EQ(waitpid(broker_pid, &status, 0), broker_pid); | 88 ASSERT_EQ(waitpid(broker_pid, &status, 0), broker_pid); |
84 ASSERT_TRUE(WIFEXITED(status)); | 89 ASSERT_TRUE(WIFEXITED(status)); |
85 ASSERT_EQ(WEXITSTATUS(status), 0); | 90 ASSERT_EQ(WEXITSTATUS(status), 0); |
86 } | 91 } |
87 | 92 |
88 TEST(BrokerProcess, TestOpenAccessNull) { | 93 TEST(BrokerProcess, TestOpenAccessNull) { |
89 const std::vector<std::string> empty; | 94 const std::vector<std::string> empty; |
90 BrokerProcess open_broker(EPERM, empty, empty); | 95 BrokerProcess open_broker(EPERM, empty, empty); |
91 ASSERT_TRUE(open_broker.Init(NULL)); | 96 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback))); |
92 | 97 |
93 int fd = open_broker.Open(NULL, O_RDONLY); | 98 int fd = open_broker.Open(NULL, O_RDONLY); |
94 ASSERT_EQ(fd, -EFAULT); | 99 ASSERT_EQ(fd, -EFAULT); |
95 | 100 |
96 int ret = open_broker.Access(NULL, F_OK); | 101 int ret = open_broker.Access(NULL, F_OK); |
97 ASSERT_EQ(ret, -EFAULT); | 102 ASSERT_EQ(ret, -EFAULT); |
98 } | 103 } |
99 | 104 |
100 void TestOpenFilePerms(bool fast_check_in_client, int denied_errno) { | 105 void TestOpenFilePerms(bool fast_check_in_client, int denied_errno) { |
101 const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1"; | 106 const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1"; |
(...skipping 10 matching lines...) Expand all Loading... |
112 read_whitelist.push_back(kRW_WhiteListed); | 117 read_whitelist.push_back(kRW_WhiteListed); |
113 | 118 |
114 std::vector<std::string> write_whitelist; | 119 std::vector<std::string> write_whitelist; |
115 write_whitelist.push_back(kW_WhiteListed); | 120 write_whitelist.push_back(kW_WhiteListed); |
116 write_whitelist.push_back(kRW_WhiteListed); | 121 write_whitelist.push_back(kRW_WhiteListed); |
117 | 122 |
118 BrokerProcess open_broker(denied_errno, | 123 BrokerProcess open_broker(denied_errno, |
119 read_whitelist, | 124 read_whitelist, |
120 write_whitelist, | 125 write_whitelist, |
121 fast_check_in_client); | 126 fast_check_in_client); |
122 ASSERT_TRUE(open_broker.Init(NULL)); | 127 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback))); |
123 | 128 |
124 int fd = -1; | 129 int fd = -1; |
125 fd = open_broker.Open(kR_WhiteListed, O_RDONLY); | 130 fd = open_broker.Open(kR_WhiteListed, O_RDONLY); |
126 ASSERT_EQ(fd, -ENOENT); | 131 ASSERT_EQ(fd, -ENOENT); |
127 fd = open_broker.Open(kR_WhiteListed, O_WRONLY); | 132 fd = open_broker.Open(kR_WhiteListed, O_WRONLY); |
128 ASSERT_EQ(fd, -denied_errno); | 133 ASSERT_EQ(fd, -denied_errno); |
129 fd = open_broker.Open(kR_WhiteListed, O_RDWR); | 134 fd = open_broker.Open(kR_WhiteListed, O_RDWR); |
130 ASSERT_EQ(fd, -denied_errno); | 135 ASSERT_EQ(fd, -denied_errno); |
131 int ret = -1; | 136 int ret = -1; |
132 ret = open_broker.Access(kR_WhiteListed, F_OK); | 137 ret = open_broker.Access(kR_WhiteListed, F_OK); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 // expected. | 268 // expected. |
264 } | 269 } |
265 | 270 |
266 void TestOpenCpuinfo(bool fast_check_in_client) { | 271 void TestOpenCpuinfo(bool fast_check_in_client) { |
267 const char kFileCpuInfo[] = "/proc/cpuinfo"; | 272 const char kFileCpuInfo[] = "/proc/cpuinfo"; |
268 std::vector<std::string> read_whitelist; | 273 std::vector<std::string> read_whitelist; |
269 read_whitelist.push_back(kFileCpuInfo); | 274 read_whitelist.push_back(kFileCpuInfo); |
270 | 275 |
271 scoped_ptr<BrokerProcess> open_broker(new BrokerProcess( | 276 scoped_ptr<BrokerProcess> open_broker(new BrokerProcess( |
272 EPERM, read_whitelist, std::vector<std::string>(), fast_check_in_client)); | 277 EPERM, read_whitelist, std::vector<std::string>(), fast_check_in_client)); |
273 ASSERT_TRUE(open_broker->Init(NULL)); | 278 ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback))); |
274 pid_t broker_pid = open_broker->broker_pid(); | 279 pid_t broker_pid = open_broker->broker_pid(); |
275 | 280 |
276 int fd = -1; | 281 int fd = -1; |
277 fd = open_broker->Open(kFileCpuInfo, O_RDWR); | 282 fd = open_broker->Open(kFileCpuInfo, O_RDWR); |
278 ScopedFD fd_closer(&fd); | 283 ScopedFD fd_closer(&fd); |
279 ASSERT_EQ(fd, -EPERM); | 284 ASSERT_EQ(fd, -EPERM); |
280 | 285 |
281 // Check we can read /proc/cpuinfo. | 286 // Check we can read /proc/cpuinfo. |
282 int can_access = open_broker->Access(kFileCpuInfo, R_OK); | 287 int can_access = open_broker->Access(kFileCpuInfo, R_OK); |
283 ASSERT_EQ(can_access, 0); | 288 ASSERT_EQ(can_access, 0); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 } | 338 } |
334 | 339 |
335 TEST(BrokerProcess, OpenFileRW) { | 340 TEST(BrokerProcess, OpenFileRW) { |
336 ScopedTemporaryFile tempfile; | 341 ScopedTemporaryFile tempfile; |
337 const char* tempfile_name = tempfile.full_file_name(); | 342 const char* tempfile_name = tempfile.full_file_name(); |
338 | 343 |
339 std::vector<std::string> whitelist; | 344 std::vector<std::string> whitelist; |
340 whitelist.push_back(tempfile_name); | 345 whitelist.push_back(tempfile_name); |
341 | 346 |
342 BrokerProcess open_broker(EPERM, whitelist, whitelist); | 347 BrokerProcess open_broker(EPERM, whitelist, whitelist); |
343 ASSERT_TRUE(open_broker.Init(NULL)); | 348 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback))); |
344 | 349 |
345 // Check we can access that file with read or write. | 350 // Check we can access that file with read or write. |
346 int can_access = open_broker.Access(tempfile_name, R_OK | W_OK); | 351 int can_access = open_broker.Access(tempfile_name, R_OK | W_OK); |
347 ASSERT_EQ(can_access, 0); | 352 ASSERT_EQ(can_access, 0); |
348 | 353 |
349 int tempfile2 = -1; | 354 int tempfile2 = -1; |
350 tempfile2 = open_broker.Open(tempfile_name, O_RDWR); | 355 tempfile2 = open_broker.Open(tempfile_name, O_RDWR); |
351 ASSERT_GE(tempfile2, 0); | 356 ASSERT_GE(tempfile2, 0); |
352 | 357 |
353 // Write to the descriptor opened by the broker. | 358 // Write to the descriptor opened by the broker. |
(...skipping 16 matching lines...) Expand all Loading... |
370 // and we want this to happen in a subprocess. | 375 // and we want this to happen in a subprocess. |
371 SANDBOX_TEST(BrokerProcess, BrokerDied) { | 376 SANDBOX_TEST(BrokerProcess, BrokerDied) { |
372 std::vector<std::string> read_whitelist; | 377 std::vector<std::string> read_whitelist; |
373 read_whitelist.push_back("/proc/cpuinfo"); | 378 read_whitelist.push_back("/proc/cpuinfo"); |
374 | 379 |
375 BrokerProcess open_broker(EPERM, | 380 BrokerProcess open_broker(EPERM, |
376 read_whitelist, | 381 read_whitelist, |
377 std::vector<std::string>(), | 382 std::vector<std::string>(), |
378 true /* fast_check_in_client */, | 383 true /* fast_check_in_client */, |
379 true /* quiet_failures_for_tests */); | 384 true /* quiet_failures_for_tests */); |
380 SANDBOX_ASSERT(open_broker.Init(NULL)); | 385 SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback))); |
381 pid_t broker_pid = open_broker.broker_pid(); | 386 pid_t broker_pid = open_broker.broker_pid(); |
382 SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0); | 387 SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0); |
383 | 388 |
384 // Now we check that the broker has exited properly. | 389 // Now we check that the broker has exited properly. |
385 int status = 0; | 390 int status = 0; |
386 SANDBOX_ASSERT(waitpid(broker_pid, &status, 0) == broker_pid); | 391 SANDBOX_ASSERT(waitpid(broker_pid, &status, 0) == broker_pid); |
387 SANDBOX_ASSERT(WIFSIGNALED(status)); | 392 SANDBOX_ASSERT(WIFSIGNALED(status)); |
388 SANDBOX_ASSERT(WTERMSIG(status) == SIGKILL); | 393 SANDBOX_ASSERT(WTERMSIG(status) == SIGKILL); |
389 // Check that doing Open with a dead broker won't SIGPIPE us. | 394 // Check that doing Open with a dead broker won't SIGPIPE us. |
390 SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM); | 395 SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM); |
391 SANDBOX_ASSERT(open_broker.Access("/proc/cpuinfo", O_RDONLY) == -ENOMEM); | 396 SANDBOX_ASSERT(open_broker.Access("/proc/cpuinfo", O_RDONLY) == -ENOMEM); |
392 } | 397 } |
393 | 398 |
394 void TestOpenComplexFlags(bool fast_check_in_client) { | 399 void TestOpenComplexFlags(bool fast_check_in_client) { |
395 const char kCpuInfo[] = "/proc/cpuinfo"; | 400 const char kCpuInfo[] = "/proc/cpuinfo"; |
396 std::vector<std::string> whitelist; | 401 std::vector<std::string> whitelist; |
397 whitelist.push_back(kCpuInfo); | 402 whitelist.push_back(kCpuInfo); |
398 | 403 |
399 BrokerProcess open_broker(EPERM, | 404 BrokerProcess open_broker(EPERM, |
400 whitelist, | 405 whitelist, |
401 whitelist, | 406 whitelist, |
402 fast_check_in_client); | 407 fast_check_in_client); |
403 ASSERT_TRUE(open_broker.Init(NULL)); | 408 ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback))); |
404 // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK. | 409 // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK. |
405 int fd = -1; | 410 int fd = -1; |
406 int ret = 0; | 411 int ret = 0; |
407 fd = open_broker.Open(kCpuInfo, O_RDONLY); | 412 fd = open_broker.Open(kCpuInfo, O_RDONLY); |
408 ASSERT_GE(fd, 0); | 413 ASSERT_GE(fd, 0); |
409 ret = fcntl(fd, F_GETFL); | 414 ret = fcntl(fd, F_GETFL); |
410 ASSERT_NE(-1, ret); | 415 ASSERT_NE(-1, ret); |
411 // The descriptor shouldn't have the O_CLOEXEC attribute, nor O_NONBLOCK. | 416 // The descriptor shouldn't have the O_CLOEXEC attribute, nor O_NONBLOCK. |
412 ASSERT_EQ(0, ret & (O_CLOEXEC | O_NONBLOCK)); | 417 ASSERT_EQ(0, ret & (O_CLOEXEC | O_NONBLOCK)); |
413 ASSERT_EQ(0, close(fd)); | 418 ASSERT_EQ(0, close(fd)); |
(...skipping 21 matching lines...) Expand all Loading... |
435 // expected. | 440 // expected. |
436 } | 441 } |
437 | 442 |
438 TEST(BrokerProcess, OpenComplexFlagsNoClientCheck) { | 443 TEST(BrokerProcess, OpenComplexFlagsNoClientCheck) { |
439 TestOpenComplexFlags(false /* fast_check_in_client */); | 444 TestOpenComplexFlags(false /* fast_check_in_client */); |
440 // Don't do anything here, so that ASSERT works in the subfunction as | 445 // Don't do anything here, so that ASSERT works in the subfunction as |
441 // expected. | 446 // expected. |
442 } | 447 } |
443 | 448 |
444 } // namespace sandbox | 449 } // namespace sandbox |
OLD | NEW |