12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sandbox/linux/services/broker_process.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include <sys/resource.h>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/stat.h>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/types.h>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/wait.h>
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <unistd.h>
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include <algorithm>
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/basictypes.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/file_util.h"
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/scoped_file.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/posix/eintr_wrapper.h"
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/posix/unix_domain_socket_linux.h"
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "sandbox/linux/tests/test_utils.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sandbox/linux/tests/unit_tests.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace sandbox {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass BrokerProcessTestHelper {
34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch public:
35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  static int get_ipc_socketpair(const BrokerProcess* broker) {
36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return broker->ipc_socketpair_;
37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch};
39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochnamespace {
419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Creates and open a temporary file on creation and closes
439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// and removes it on destruction.
449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Unlike base/ helpers, this does not require JNI on Android.
459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass ScopedTemporaryFile {
469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public:
479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  ScopedTemporaryFile()
489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      : fd_(-1) {
499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#if defined(OS_ANDROID)
509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    static const char file_template[] = "/data/local/tmp/ScopedTempFileXXXXXX";
519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#else
529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    static const char file_template[] = "/tmp/ScopedTempFileXXXXXX";
539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#endif  // defined(OS_ANDROID)
549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    COMPILE_ASSERT(sizeof(full_file_name_) >= sizeof(file_template),
559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch                   full_file_name_is_large_enough);
569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    memcpy(full_file_name_, file_template, sizeof(file_template));
579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    fd_ = mkstemp(full_file_name_);
589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    CHECK_LE(0, fd_);
599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  }
609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  ~ScopedTemporaryFile() {
619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    CHECK_EQ(0, unlink(full_file_name_));
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    CHECK_EQ(0, IGNORE_EINTR(close(fd_)));
639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  }
649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  int fd() const { return fd_; }
669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  const char* full_file_name() const { return full_file_name_; }
679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch private:
699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  int fd_;
709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  char full_file_name_[128];
719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(ScopedTemporaryFile);
729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch};
739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool NoOpCallback() { return true; }
759ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, CreateAndDestroy) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> read_whitelist;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back("/proc/cpuinfo");
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<BrokerProcess> open_broker(
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new BrokerProcess(EPERM, read_whitelist, std::vector<std::string>()));
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Destroy the broker and check it has exited properly.
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  open_broker.reset();
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(BrokerProcess, TestOpenAccessNull) {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::vector<std::string> empty;
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(EPERM, empty, empty);
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = open_broker.Open(NULL, O_RDONLY);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -EFAULT);
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int ret = open_broker.Access(NULL, F_OK);
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -EFAULT);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TestOpenFilePerms(bool fast_check_in_client, int denied_errno) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1";
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We can't debug the init process, and shouldn't be able to access
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // its auxv file.
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char kR_WhiteListedButDenied[] = "/proc/1/auxv";
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kW_WhiteListed[] = "/proc/DOESNOTEXIST2";
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kRW_WhiteListed[] = "/proc/DOESNOTEXIST3";
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char k_NotWhitelisted[] = "/proc/DOESNOTEXIST4";
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> read_whitelist;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back(kR_WhiteListed);
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  read_whitelist.push_back(kR_WhiteListedButDenied);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back(kRW_WhiteListed);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> write_whitelist;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  write_whitelist.push_back(kW_WhiteListed);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  write_whitelist.push_back(kRW_WhiteListed);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(denied_errno,
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            read_whitelist,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            write_whitelist,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            fast_check_in_client);
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = -1;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kR_WhiteListed, O_RDONLY);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kR_WhiteListed, O_WRONLY);
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kR_WhiteListed, O_RDWR);
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int ret = -1;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, F_OK);
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, R_OK);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, W_OK);
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, R_OK | W_OK);
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, X_OK);
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, R_OK | X_OK);
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Android sometimes runs tests as root.
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // This part of the test requires a process that doesn't have
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // CAP_DAC_OVERRIDE. We check against a root euid as a proxy for that.
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (geteuid()) {
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fd = open_broker.Open(kR_WhiteListedButDenied, O_RDONLY);
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // The broker process will allow this, but the normal permission system
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // won't.
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_EQ(fd, -EACCES);
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fd = open_broker.Open(kR_WhiteListedButDenied, O_WRONLY);
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(fd, -denied_errno);
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fd = open_broker.Open(kR_WhiteListedButDenied, O_RDWR);
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(fd, -denied_errno);
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, F_OK);
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // The normal permission system will let us check that the file exists.
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_EQ(ret, 0);
1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, R_OK);
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_EQ(ret, -EACCES);
1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, W_OK);
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(ret, -denied_errno);
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | W_OK);
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(ret, -denied_errno);
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, X_OK);
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(ret, -denied_errno);
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | X_OK);
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(ret, -denied_errno);
1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kW_WhiteListed, O_RDONLY);
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kW_WhiteListed, O_WRONLY);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kW_WhiteListed, O_RDWR);
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, F_OK);
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, R_OK);
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, W_OK);
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, R_OK | W_OK);
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, X_OK);
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, R_OK | X_OK);
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_RDONLY);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_WRONLY);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_RDWR);
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, F_OK);
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, R_OK);
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, W_OK);
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, R_OK | W_OK);
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, X_OK);
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, R_OK | X_OK);
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(k_NotWhitelisted, O_RDONLY);
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(k_NotWhitelisted, O_WRONLY);
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(k_NotWhitelisted, O_RDWR);
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, F_OK);
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, R_OK);
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, W_OK);
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, R_OK | W_OK);
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, X_OK);
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, R_OK | X_OK);
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We have some extra sanity check for clearly wrong values.
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_RDONLY | O_WRONLY | O_RDWR);
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // It makes no sense to allow O_CREAT in a 2-parameters open. Ensure this
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is denied.
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_RDWR | O_CREAT);
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Run the same thing twice. The second time, we make sure that no security
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// check is performed on the client.
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, OpenFilePermsWithClientCheck) {
2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TestOpenFilePerms(true /* fast_check_in_client */, EPERM);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, OpenOpenFilePermsNoClientCheck) {
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TestOpenFilePerms(false /* fast_check_in_client */, EPERM);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Run the same twice again, but with ENOENT instead of EPERM.
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(BrokerProcess, OpenFilePermsWithClientCheckNoEnt) {
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TestOpenFilePerms(true /* fast_check_in_client */, ENOENT);
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // expected.
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(BrokerProcess, OpenOpenFilePermsNoClientCheckNoEnt) {
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TestOpenFilePerms(false /* fast_check_in_client */, ENOENT);
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // expected.
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TestOpenCpuinfo(bool fast_check_in_client) {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kFileCpuInfo[] = "/proc/cpuinfo";
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> read_whitelist;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back(kFileCpuInfo);
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<BrokerProcess> open_broker(new BrokerProcess(
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      EPERM, read_whitelist, std::vector<std::string>(), fast_check_in_client));
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = -1;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker->Open(kFileCpuInfo, O_RDWR);
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD fd_closer(fd);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -EPERM);
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check we can read /proc/cpuinfo.
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int can_access = open_broker->Access(kFileCpuInfo, R_OK);
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(can_access, 0);
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  can_access = open_broker->Access(kFileCpuInfo, W_OK);
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(can_access, -EPERM);
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check we can not write /proc/cpuinfo.
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open cpuinfo via the broker.
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int cpuinfo_fd = open_broker->Open(kFileCpuInfo, O_RDONLY);
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD cpuinfo_fd_closer(cpuinfo_fd);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GE(cpuinfo_fd, 0);
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char buf[3];
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(buf, 0, sizeof(buf));
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int read_len1 = read(cpuinfo_fd, buf, sizeof(buf));
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GT(read_len1, 0);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open cpuinfo directly.
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int cpuinfo_fd2 = open(kFileCpuInfo, O_RDONLY);
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD cpuinfo_fd2_closer(cpuinfo_fd2);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GE(cpuinfo_fd2, 0);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char buf2[3];
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(buf2, 1, sizeof(buf2));
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int read_len2 = read(cpuinfo_fd2, buf2, sizeof(buf2));
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GT(read_len1, 0);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The following is not guaranteed true, but will be in practice.
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(read_len1, read_len2);
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compare the cpuinfo as returned by the broker with the one we opened
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ourselves.
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(memcmp(buf, buf2, read_len1), 0);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  open_broker.reset();
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Run the same thing twice. The second time, we make sure that no security
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// check is performed on the client.
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, OpenCpuinfoWithClientCheck) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestOpenCpuinfo(true /* fast_check_in_client */);
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, OpenCpuinfoNoClientCheck) {
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestOpenCpuinfo(false /* fast_check_in_client */);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(BrokerProcess, OpenFileRW) {
3359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  ScopedTemporaryFile tempfile;
3369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  const char* tempfile_name = tempfile.full_file_name();
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> whitelist;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  whitelist.push_back(tempfile_name);
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(EPERM, whitelist, whitelist);
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check we can access that file with read or write.
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int can_access = open_broker.Access(tempfile_name, R_OK | W_OK);
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(can_access, 0);
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int tempfile2 = -1;
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tempfile2 = open_broker.Open(tempfile_name, O_RDWR);
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GE(tempfile2, 0);
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Write to the descriptor opened by the broker.
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char test_text[] = "TESTTESTTEST";
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ssize_t len = write(tempfile2, test_text, sizeof(test_text));
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Read back from the original file descriptor what we wrote through
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the descriptor provided by the broker.
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char buf[1024];
3609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  len = read(tempfile.fd(), buf, sizeof(buf));
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0);
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(close(tempfile2), 0);
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// SANDBOX_TEST because the process could die with a SIGPIPE
3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// and we want this to happen in a subprocess.
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SANDBOX_TEST(BrokerProcess, BrokerDied) {
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> read_whitelist;
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back("/proc/cpuinfo");
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(EPERM,
3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            read_whitelist,
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            std::vector<std::string>(),
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            true /* fast_check_in_client */,
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            true /* quiet_failures_for_tests */);
379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const pid_t broker_pid = open_broker.broker_pid();
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0);
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Now we check that the broker has been signaled, but do not reap it.
384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  siginfo_t process_info;
385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(HANDLE_EINTR(waitid(
386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     P_PID, broker_pid, &process_info, WEXITED | WNOWAIT)) ==
387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 0);
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(broker_pid == process_info.si_pid);
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(CLD_KILLED == process_info.si_code);
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(SIGKILL == process_info.si_status);
391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Check that doing Open with a dead broker won't SIGPIPE us.
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SANDBOX_ASSERT(open_broker.Access("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TestOpenComplexFlags(bool fast_check_in_client) {
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char kCpuInfo[] = "/proc/cpuinfo";
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> whitelist;
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  whitelist.push_back(kCpuInfo);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(EPERM,
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            whitelist,
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            whitelist,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            fast_check_in_client);
406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK.
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = -1;
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int ret = 0;
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fd = open_broker.Open(kCpuInfo, O_RDONLY);
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GE(fd, 0);
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = fcntl(fd, F_GETFL);
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NE(-1, ret);
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The descriptor shouldn't have the O_CLOEXEC attribute, nor O_NONBLOCK.
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, ret & (O_CLOEXEC | O_NONBLOCK));
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, close(fd));
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fd = open_broker.Open(kCpuInfo, O_RDONLY | O_CLOEXEC);
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_GE(fd, 0);
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = fcntl(fd, F_GETFD);
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NE(-1, ret);
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Important: use F_GETFD, not F_GETFL. The O_CLOEXEC flag in F_GETFL
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // is actually not used by the kernel.
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(FD_CLOEXEC & ret);
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, close(fd));
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fd = open_broker.Open(kCpuInfo, O_RDONLY | O_NONBLOCK);
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_GE(fd, 0);
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = fcntl(fd, F_GETFL);
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NE(-1, ret);
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(O_NONBLOCK & ret);
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, close(fd));
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(BrokerProcess, OpenComplexFlagsWithClientCheck) {
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestOpenComplexFlags(true /* fast_check_in_client */);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(BrokerProcess, OpenComplexFlagsNoClientCheck) {
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestOpenComplexFlags(false /* fast_check_in_client */);
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
447a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// We need to allow noise because the broker will log when it receives our
448a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// bogus IPCs.
449a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochSANDBOX_TEST_ALLOW_NOISE(BrokerProcess, RecvMsgDescriptorLeak) {
450a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Find the four lowest available file descriptors.
451a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int available_fds[4];
452a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SANDBOX_ASSERT(0 == pipe(available_fds));
453a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SANDBOX_ASSERT(0 == pipe(available_fds + 2));
454a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
455a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Save one FD to send to the broker later, and close the others.
456a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::ScopedFD message_fd(available_fds[0]);
457a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (size_t i = 1; i < arraysize(available_fds); i++) {
458a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SANDBOX_ASSERT(0 == IGNORE_EINTR(close(available_fds[i])));
459a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
460a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
461a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Lower our file descriptor limit to just allow three more file descriptors
462a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // to be allocated.  (N.B., RLIMIT_NOFILE doesn't limit the number of file
463a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // descriptors a process can have: it only limits the highest value that can
464a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // be assigned to newly-created descriptors allocated by the process.)
465a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  const rlim_t fd_limit =
466a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      1 + *std::max_element(available_fds,
467a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            available_fds + arraysize(available_fds));
468a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
469a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Valgrind doesn't allow changing the hard descriptor limit, so we only
470a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // change the soft descriptor limit here.
471a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  struct rlimit rlim;
472a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SANDBOX_ASSERT(0 == getrlimit(RLIMIT_NOFILE, &rlim));
473a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SANDBOX_ASSERT(fd_limit <= rlim.rlim_cur);
474a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  rlim.rlim_cur = fd_limit;
475a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SANDBOX_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &rlim));
476a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
477a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  static const char kCpuInfo[] = "/proc/cpuinfo";
478a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::vector<std::string> read_whitelist;
479a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  read_whitelist.push_back(kCpuInfo);
480a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
481a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrokerProcess open_broker(EPERM, read_whitelist, std::vector<std::string>());
482a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
483a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
484a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  const int ipc_fd = BrokerProcessTestHelper::get_ipc_socketpair(&open_broker);
485a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SANDBOX_ASSERT(ipc_fd >= 0);
486a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
487a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  static const char kBogus[] = "not a pickle";
488a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::vector<int> fds;
489a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  fds.push_back(message_fd.get());
490a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
491a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // The broker process should only have a couple spare file descriptors
492a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // available, but for good measure we send it fd_limit bogus IPCs anyway.
493a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (rlim_t i = 0; i < fd_limit; ++i) {
494a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SANDBOX_ASSERT(
495a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        UnixDomainSocket::SendMsg(ipc_fd, kBogus, sizeof(kBogus), fds));
496a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
497a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
498a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  const int fd = open_broker.Open(kCpuInfo, O_RDONLY);
499a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SANDBOX_ASSERT(fd >= 0);
500a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SANDBOX_ASSERT(0 == IGNORE_EINTR(close(fd)));
501a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
502a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace sandbox
504