broker_process_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/stat.h>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/types.h>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/wait.h>
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <unistd.h>
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/basictypes.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h"
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/file_util.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/scoped_file.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/posix/eintr_wrapper.h"
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "sandbox/linux/tests/test_utils.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sandbox/linux/tests/unit_tests.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace sandbox {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochnamespace {
319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Creates and open a temporary file on creation and closes
339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// and removes it on destruction.
349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Unlike base/ helpers, this does not require JNI on Android.
359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass ScopedTemporaryFile {
369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public:
379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  ScopedTemporaryFile()
389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch      : fd_(-1) {
399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#if defined(OS_ANDROID)
409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    static const char file_template[] = "/data/local/tmp/ScopedTempFileXXXXXX";
419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#else
429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    static const char file_template[] = "/tmp/ScopedTempFileXXXXXX";
439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#endif  // defined(OS_ANDROID)
449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    COMPILE_ASSERT(sizeof(full_file_name_) >= sizeof(file_template),
459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch                   full_file_name_is_large_enough);
469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    memcpy(full_file_name_, file_template, sizeof(file_template));
479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    fd_ = mkstemp(full_file_name_);
489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    CHECK_LE(0, fd_);
499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  }
509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  ~ScopedTemporaryFile() {
519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    CHECK_EQ(0, unlink(full_file_name_));
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    CHECK_EQ(0, IGNORE_EINTR(close(fd_)));
539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  }
549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  int fd() const { return fd_; }
569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  const char* full_file_name() const { return full_file_name_; }
579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch private:
599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  int fd_;
609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  char full_file_name_[128];
619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(ScopedTemporaryFile);
629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch};
639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool NoOpCallback() { return true; }
659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, CreateAndDestroy) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> read_whitelist;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back("/proc/cpuinfo");
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<BrokerProcess> open_broker(
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new BrokerProcess(EPERM, read_whitelist, std::vector<std::string>()));
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Destroy the broker and check it has exited properly.
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  open_broker.reset();
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(BrokerProcess, TestOpenAccessNull) {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::vector<std::string> empty;
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(EPERM, empty, empty);
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = open_broker.Open(NULL, O_RDONLY);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -EFAULT);
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int ret = open_broker.Access(NULL, F_OK);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -EFAULT);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TestOpenFilePerms(bool fast_check_in_client, int denied_errno) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kR_WhiteListed[] = "/proc/DOESNOTEXIST1";
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We can't debug the init process, and shouldn't be able to access
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // its auxv file.
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char kR_WhiteListedButDenied[] = "/proc/1/auxv";
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kW_WhiteListed[] = "/proc/DOESNOTEXIST2";
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kRW_WhiteListed[] = "/proc/DOESNOTEXIST3";
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char k_NotWhitelisted[] = "/proc/DOESNOTEXIST4";
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> read_whitelist;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back(kR_WhiteListed);
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  read_whitelist.push_back(kR_WhiteListedButDenied);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back(kRW_WhiteListed);
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> write_whitelist;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  write_whitelist.push_back(kW_WhiteListed);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  write_whitelist.push_back(kRW_WhiteListed);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(denied_errno,
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            read_whitelist,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            write_whitelist,
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            fast_check_in_client);
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = -1;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kR_WhiteListed, O_RDONLY);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kR_WhiteListed, O_WRONLY);
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kR_WhiteListed, O_RDWR);
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int ret = -1;
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, F_OK);
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, R_OK);
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, W_OK);
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, R_OK | W_OK);
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, X_OK);
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kR_WhiteListed, R_OK | X_OK);
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Android sometimes runs tests as root.
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // This part of the test requires a process that doesn't have
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // CAP_DAC_OVERRIDE. We check against a root euid as a proxy for that.
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (geteuid()) {
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fd = open_broker.Open(kR_WhiteListedButDenied, O_RDONLY);
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // The broker process will allow this, but the normal permission system
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // won't.
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_EQ(fd, -EACCES);
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fd = open_broker.Open(kR_WhiteListedButDenied, O_WRONLY);
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(fd, -denied_errno);
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fd = open_broker.Open(kR_WhiteListedButDenied, O_RDWR);
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(fd, -denied_errno);
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, F_OK);
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // The normal permission system will let us check that the file exists.
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_EQ(ret, 0);
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, R_OK);
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_EQ(ret, -EACCES);
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, W_OK);
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(ret, -denied_errno);
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | W_OK);
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(ret, -denied_errno);
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, X_OK);
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(ret, -denied_errno);
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ret = open_broker.Access(kR_WhiteListedButDenied, R_OK | X_OK);
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(ret, -denied_errno);
1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kW_WhiteListed, O_RDONLY);
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kW_WhiteListed, O_WRONLY);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kW_WhiteListed, O_RDWR);
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, F_OK);
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, R_OK);
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, W_OK);
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, R_OK | W_OK);
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, X_OK);
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kW_WhiteListed, R_OK | X_OK);
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_RDONLY);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_WRONLY);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_RDWR);
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -ENOENT);
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, F_OK);
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, R_OK);
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, W_OK);
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, R_OK | W_OK);
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(ret, -ENOENT);
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, X_OK);
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(kRW_WhiteListed, R_OK | X_OK);
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(k_NotWhitelisted, O_RDONLY);
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(k_NotWhitelisted, O_WRONLY);
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker.Open(k_NotWhitelisted, O_RDWR);
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, F_OK);
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, R_OK);
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, W_OK);
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, R_OK | W_OK);
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, X_OK);
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = open_broker.Access(k_NotWhitelisted, R_OK | X_OK);
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(ret, -denied_errno);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We have some extra sanity check for clearly wrong values.
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_RDONLY | O_WRONLY | O_RDWR);
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // It makes no sense to allow O_CREAT in a 2-parameters open. Ensure this
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is denied.
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  fd = open_broker.Open(kRW_WhiteListed, O_RDWR | O_CREAT);
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(fd, -denied_errno);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Run the same thing twice. The second time, we make sure that no security
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// check is performed on the client.
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, OpenFilePermsWithClientCheck) {
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TestOpenFilePerms(true /* fast_check_in_client */, EPERM);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, OpenOpenFilePermsNoClientCheck) {
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TestOpenFilePerms(false /* fast_check_in_client */, EPERM);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Run the same twice again, but with ENOENT instead of EPERM.
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(BrokerProcess, OpenFilePermsWithClientCheckNoEnt) {
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TestOpenFilePerms(true /* fast_check_in_client */, ENOENT);
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // expected.
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(BrokerProcess, OpenOpenFilePermsNoClientCheckNoEnt) {
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TestOpenFilePerms(false /* fast_check_in_client */, ENOENT);
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // expected.
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TestOpenCpuinfo(bool fast_check_in_client) {
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char kFileCpuInfo[] = "/proc/cpuinfo";
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> read_whitelist;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back(kFileCpuInfo);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<BrokerProcess> open_broker(new BrokerProcess(
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      EPERM, read_whitelist, std::vector<std::string>(), fast_check_in_client));
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker->Init(base::Bind(&NoOpCallback)));
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = -1;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = open_broker->Open(kFileCpuInfo, O_RDWR);
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD fd_closer(fd);
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fd, -EPERM);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check we can read /proc/cpuinfo.
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int can_access = open_broker->Access(kFileCpuInfo, R_OK);
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(can_access, 0);
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  can_access = open_broker->Access(kFileCpuInfo, W_OK);
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(can_access, -EPERM);
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check we can not write /proc/cpuinfo.
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open cpuinfo via the broker.
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int cpuinfo_fd = open_broker->Open(kFileCpuInfo, O_RDONLY);
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD cpuinfo_fd_closer(cpuinfo_fd);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GE(cpuinfo_fd, 0);
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char buf[3];
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(buf, 0, sizeof(buf));
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int read_len1 = read(cpuinfo_fd, buf, sizeof(buf));
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GT(read_len1, 0);
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open cpuinfo directly.
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int cpuinfo_fd2 = open(kFileCpuInfo, O_RDONLY);
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFD cpuinfo_fd2_closer(cpuinfo_fd2);
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GE(cpuinfo_fd2, 0);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char buf2[3];
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(buf2, 1, sizeof(buf2));
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int read_len2 = read(cpuinfo_fd2, buf2, sizeof(buf2));
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GT(read_len1, 0);
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The following is not guaranteed true, but will be in practice.
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(read_len1, read_len2);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compare the cpuinfo as returned by the broker with the one we opened
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ourselves.
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(memcmp(buf, buf2, read_len1), 0);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(TestUtils::CurrentProcessHasChildren());
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  open_broker.reset();
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_FALSE(TestUtils::CurrentProcessHasChildren());
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Run the same thing twice. The second time, we make sure that no security
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// check is performed on the client.
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, OpenCpuinfoWithClientCheck) {
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestOpenCpuinfo(true /* fast_check_in_client */);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BrokerProcess, OpenCpuinfoNoClientCheck) {
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestOpenCpuinfo(false /* fast_check_in_client */);
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(BrokerProcess, OpenFileRW) {
3259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  ScopedTemporaryFile tempfile;
3269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  const char* tempfile_name = tempfile.full_file_name();
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> whitelist;
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  whitelist.push_back(tempfile_name);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(EPERM, whitelist, whitelist);
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check we can access that file with read or write.
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int can_access = open_broker.Access(tempfile_name, R_OK | W_OK);
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(can_access, 0);
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int tempfile2 = -1;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tempfile2 = open_broker.Open(tempfile_name, O_RDWR);
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GE(tempfile2, 0);
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Write to the descriptor opened by the broker.
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char test_text[] = "TESTTESTTEST";
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ssize_t len = write(tempfile2, test_text, sizeof(test_text));
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Read back from the original file descriptor what we wrote through
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the descriptor provided by the broker.
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char buf[1024];
3509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  len = read(tempfile.fd(), buf, sizeof(buf));
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(len, static_cast<ssize_t>(sizeof(test_text)));
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(memcmp(test_text, buf, sizeof(test_text)), 0);
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(close(tempfile2), 0);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// SANDBOX_TEST because the process could die with a SIGPIPE
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// and we want this to happen in a subprocess.
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SANDBOX_TEST(BrokerProcess, BrokerDied) {
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> read_whitelist;
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_whitelist.push_back("/proc/cpuinfo");
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(EPERM,
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            read_whitelist,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            std::vector<std::string>(),
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            true /* fast_check_in_client */,
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            true /* quiet_failures_for_tests */);
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const pid_t broker_pid = open_broker.broker_pid();
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(kill(broker_pid, SIGKILL) == 0);
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Now we check that the broker has been signaled, but do not reap it.
374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  siginfo_t process_info;
375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(HANDLE_EINTR(waitid(
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     P_PID, broker_pid, &process_info, WEXITED | WNOWAIT)) ==
377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 0);
378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(broker_pid == process_info.si_pid);
379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(CLD_KILLED == process_info.si_code);
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SANDBOX_ASSERT(SIGKILL == process_info.si_status);
381a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Check that doing Open with a dead broker won't SIGPIPE us.
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(open_broker.Open("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SANDBOX_ASSERT(open_broker.Access("/proc/cpuinfo", O_RDONLY) == -ENOMEM);
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TestOpenComplexFlags(bool fast_check_in_client) {
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char kCpuInfo[] = "/proc/cpuinfo";
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> whitelist;
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  whitelist.push_back(kCpuInfo);
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrokerProcess open_broker(EPERM,
3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            whitelist,
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            whitelist,
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            fast_check_in_client);
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(open_broker.Init(base::Bind(&NoOpCallback)));
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test that we do the right thing for O_CLOEXEC and O_NONBLOCK.
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = -1;
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int ret = 0;
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fd = open_broker.Open(kCpuInfo, O_RDONLY);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GE(fd, 0);
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = fcntl(fd, F_GETFL);
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NE(-1, ret);
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The descriptor shouldn't have the O_CLOEXEC attribute, nor O_NONBLOCK.
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, ret & (O_CLOEXEC | O_NONBLOCK));
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, close(fd));
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fd = open_broker.Open(kCpuInfo, O_RDONLY | O_CLOEXEC);
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_GE(fd, 0);
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = fcntl(fd, F_GETFD);
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NE(-1, ret);
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Important: use F_GETFD, not F_GETFL. The O_CLOEXEC flag in F_GETFL
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // is actually not used by the kernel.
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(FD_CLOEXEC & ret);
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, close(fd));
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fd = open_broker.Open(kCpuInfo, O_RDONLY | O_NONBLOCK);
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_GE(fd, 0);
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ret = fcntl(fd, F_GETFL);
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NE(-1, ret);
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(O_NONBLOCK & ret);
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, close(fd));
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(BrokerProcess, OpenComplexFlagsWithClientCheck) {
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestOpenComplexFlags(true /* fast_check_in_client */);
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(BrokerProcess, OpenComplexFlagsNoClientCheck) {
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestOpenComplexFlags(false /* fast_check_in_client */);
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't do anything here, so that ASSERT works in the subfunction as
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected.
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace sandbox
438