| 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 |