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