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/syscall_broker/broker_process.h" | 5 #include "sandbox/linux/syscall_broker/broker_process.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <poll.h> |
9 #include <sys/resource.h> | 10 #include <sys/resource.h> |
10 #include <sys/stat.h> | 11 #include <sys/stat.h> |
11 #include <sys/types.h> | 12 #include <sys/types.h> |
12 #include <sys/wait.h> | 13 #include <sys/wait.h> |
13 #include <unistd.h> | 14 #include <unistd.h> |
14 | 15 |
15 #include <algorithm> | 16 #include <algorithm> |
16 #include <string> | 17 #include <string> |
17 #include <vector> | 18 #include <vector> |
18 | 19 |
19 #include "base/basictypes.h" | 20 #include "base/basictypes.h" |
20 #include "base/bind.h" | 21 #include "base/bind.h" |
21 #include "base/files/file_util.h" | 22 #include "base/files/file_util.h" |
22 #include "base/files/scoped_file.h" | 23 #include "base/files/scoped_file.h" |
23 #include "base/logging.h" | 24 #include "base/logging.h" |
24 #include "base/memory/scoped_ptr.h" | 25 #include "base/memory/scoped_ptr.h" |
25 #include "base/posix/eintr_wrapper.h" | 26 #include "base/posix/eintr_wrapper.h" |
26 #include "base/posix/unix_domain_socket_linux.h" | 27 #include "base/posix/unix_domain_socket_linux.h" |
27 #include "sandbox/linux/tests/scoped_temporary_file.h" | 28 #include "sandbox/linux/tests/scoped_temporary_file.h" |
28 #include "sandbox/linux/tests/test_utils.h" | 29 #include "sandbox/linux/tests/test_utils.h" |
29 #include "sandbox/linux/tests/unit_tests.h" | 30 #include "sandbox/linux/tests/unit_tests.h" |
30 #include "testing/gtest/include/gtest/gtest.h" | 31 #include "testing/gtest/include/gtest/gtest.h" |
31 | 32 |
32 namespace sandbox { | 33 namespace sandbox { |
33 | 34 |
| 35 namespace syscall_broker { |
| 36 |
34 class BrokerProcessTestHelper { | 37 class BrokerProcessTestHelper { |
35 public: | 38 public: |
| 39 static void CloseChannel(BrokerProcess* broker) { broker->CloseChannel(); } |
36 static int get_ipc_socketpair(const BrokerProcess* broker) { | 40 static int get_ipc_socketpair(const BrokerProcess* broker) { |
37 return broker->ipc_socketpair_; | 41 return broker->ipc_socketpair_; |
38 } | 42 } |
39 }; | 43 }; |
40 | 44 |
41 namespace { | 45 namespace { |
42 | 46 |
43 bool NoOpCallback() { | 47 bool NoOpCallback() { |
44 return true; | 48 return true; |
45 } | 49 } |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 for (rlim_t i = 0; i < fd_limit; ++i) { | 469 for (rlim_t i = 0; i < fd_limit; ++i) { |
466 SANDBOX_ASSERT( | 470 SANDBOX_ASSERT( |
467 UnixDomainSocket::SendMsg(ipc_fd, kBogus, sizeof(kBogus), fds)); | 471 UnixDomainSocket::SendMsg(ipc_fd, kBogus, sizeof(kBogus), fds)); |
468 } | 472 } |
469 | 473 |
470 const int fd = open_broker.Open(kCpuInfo, O_RDONLY); | 474 const int fd = open_broker.Open(kCpuInfo, O_RDONLY); |
471 SANDBOX_ASSERT(fd >= 0); | 475 SANDBOX_ASSERT(fd >= 0); |
472 SANDBOX_ASSERT(0 == IGNORE_EINTR(close(fd))); | 476 SANDBOX_ASSERT(0 == IGNORE_EINTR(close(fd))); |
473 } | 477 } |
474 | 478 |
| 479 bool CloseFD(int fd) { |
| 480 PCHECK(0 == IGNORE_EINTR(close(fd))); |
| 481 return true; |
| 482 } |
| 483 |
| 484 // Return true if the other end of the |reader| pipe was closed, |
| 485 // false if |timeout_in_seconds| was reached or another event |
| 486 // or error occured. |
| 487 bool WaitForClosedPipeWriter(int reader, int timeout_in_ms) { |
| 488 struct pollfd poll_fd = {reader, POLLIN | POLLRDHUP, 0}; |
| 489 const int num_events = HANDLE_EINTR(poll(&poll_fd, 1, timeout_in_ms)); |
| 490 if (1 == num_events && poll_fd.revents | POLLHUP) |
| 491 return true; |
| 492 return false; |
| 493 } |
| 494 |
| 495 // Closing the broker client's IPC channel should terminate the broker |
| 496 // process. |
| 497 TEST(BrokerProcess, BrokerDiesOnClosedChannel) { |
| 498 std::vector<std::string> read_whitelist; |
| 499 read_whitelist.push_back("/proc/cpuinfo"); |
| 500 |
| 501 // Get the writing end of a pipe into the broker (child) process so |
| 502 // that we can reliably detect when it dies. |
| 503 int lifeline_fds[2]; |
| 504 PCHECK(0 == pipe(lifeline_fds)); |
| 505 |
| 506 BrokerProcess open_broker(EPERM, read_whitelist, std::vector<std::string>(), |
| 507 true /* fast_check_in_client */, |
| 508 false /* quiet_failures_for_tests */); |
| 509 ASSERT_TRUE(open_broker.Init(base::Bind(&CloseFD, lifeline_fds[0]))); |
| 510 // Make sure the writing end only exists in the broker process. |
| 511 CloseFD(lifeline_fds[1]); |
| 512 base::ScopedFD reader(lifeline_fds[0]); |
| 513 |
| 514 const pid_t broker_pid = open_broker.broker_pid(); |
| 515 |
| 516 // This should cause the broker process to exit. |
| 517 BrokerProcessTestHelper::CloseChannel(&open_broker); |
| 518 |
| 519 const int kTimeoutInMilliseconds = 5000; |
| 520 const bool broker_lifeline_closed = |
| 521 WaitForClosedPipeWriter(reader.get(), kTimeoutInMilliseconds); |
| 522 // If the broker exited, its lifeline fd should be closed. |
| 523 ASSERT_TRUE(broker_lifeline_closed); |
| 524 // Now check that the broker has exited, but do not reap it. |
| 525 siginfo_t process_info; |
| 526 ASSERT_EQ(0, HANDLE_EINTR(waitid(P_PID, broker_pid, &process_info, |
| 527 WEXITED | WNOWAIT))); |
| 528 EXPECT_EQ(broker_pid, process_info.si_pid); |
| 529 EXPECT_EQ(CLD_EXITED, process_info.si_code); |
| 530 EXPECT_EQ(1, process_info.si_status); |
| 531 } |
| 532 |
| 533 } // namespace syscall_broker |
| 534 |
475 } // namespace sandbox | 535 } // namespace sandbox |
OLD | NEW |