summaryrefslogtreecommitdiffstats
path: root/chrome/common/sandbox_mac_diraccess_unittest.mm
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-11-18 18:32:45 +0000
committerBen Murdoch <benm@google.com>2010-11-18 18:38:07 +0000
commit513209b27ff55e2841eac0e4120199c23acce758 (patch)
treeaeba30bb08c5f47c57003544e378a377c297eee6 /chrome/common/sandbox_mac_diraccess_unittest.mm
parent164f7496de0fbee436b385a79ead9e3cb81a50c1 (diff)
downloadexternal_chromium-513209b27ff55e2841eac0e4120199c23acce758.zip
external_chromium-513209b27ff55e2841eac0e4120199c23acce758.tar.gz
external_chromium-513209b27ff55e2841eac0e4120199c23acce758.tar.bz2
Merge Chromium at r65505: Initial merge by git.
Change-Id: I31d8f1d8cd33caaf7f47ffa7350aef42d5fbdb45
Diffstat (limited to 'chrome/common/sandbox_mac_diraccess_unittest.mm')
-rw-r--r--chrome/common/sandbox_mac_diraccess_unittest.mm129
1 files changed, 90 insertions, 39 deletions
diff --git a/chrome/common/sandbox_mac_diraccess_unittest.mm b/chrome/common/sandbox_mac_diraccess_unittest.mm
index 5804361..fed540d 100644
--- a/chrome/common/sandbox_mac_diraccess_unittest.mm
+++ b/chrome/common/sandbox_mac_diraccess_unittest.mm
@@ -18,18 +18,16 @@ extern "C" {
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
-// Tests to exercise directory-access-related restrictions of Mac sandbox.
-
-namespace sandbox {
-
-bool QuotePlainString(const std::string& str_utf8, std::string* dst);
-bool QuoteStringForRegex(const std::string& str_utf8, std::string* dst);
-
-} // namespace sandbox
-
namespace {
static const char* kSandboxAccessPathKey = "sandbox_dir";
+static const char* kDeniedSuffix = "_denied";
+
+} // namespace
+
+// Tests need to be in the same namespace as the sandbox::Sandbox class to be
+// useable with FRIEND_TEST() declaration.
+namespace sandbox {
class MacDirAccessSandboxTest : public base::MultiProcessTest {
public:
@@ -47,8 +45,6 @@ class MacDirAccessSandboxTest : public base::MultiProcessTest {
};
TEST_F(MacDirAccessSandboxTest, StringEscape) {
- using sandbox::QuotePlainString;
-
const struct string_escape_test_data {
const char* to_escape;
const char* escaped;
@@ -64,14 +60,12 @@ TEST_F(MacDirAccessSandboxTest, StringEscape) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(string_escape_cases); ++i) {
std::string out;
std::string in(string_escape_cases[i].to_escape);
- EXPECT_TRUE(QuotePlainString(in, &out));
+ EXPECT_TRUE(Sandbox::QuotePlainString(in, &out));
EXPECT_EQ(string_escape_cases[i].escaped, out);
}
}
TEST_F(MacDirAccessSandboxTest, RegexEscape) {
- using sandbox::QuoteStringForRegex;
-
const std::string kSandboxEscapeSuffix("(/|$)");
const struct regex_test_data {
const wchar_t *to_escape;
@@ -89,24 +83,25 @@ TEST_F(MacDirAccessSandboxTest, RegexEscape) {
std::string out;
char fail_string[] = {31, 0};
char ok_string[] = {32, 0};
- EXPECT_FALSE(QuoteStringForRegex(fail_string, &out));
- EXPECT_TRUE(QuoteStringForRegex(ok_string, &out));
+ EXPECT_FALSE(Sandbox::QuoteStringForRegex(fail_string, &out));
+ EXPECT_TRUE(Sandbox::QuoteStringForRegex(ok_string, &out));
}
// Check that all characters whose values are larger than 126 [7E] are
// rejected by the regex escaping code.
{
std::string out;
- EXPECT_TRUE(QuoteStringForRegex("}", &out)); // } == 0x7D == 125
- EXPECT_FALSE(QuoteStringForRegex("~", &out)); // ~ == 0x7E == 126
- EXPECT_FALSE(QuoteStringForRegex(WideToUTF8(L"^\u2135.\u2136$"), &out));
+ EXPECT_TRUE(Sandbox::QuoteStringForRegex("}", &out)); // } == 0x7D == 125
+ EXPECT_FALSE(Sandbox::QuoteStringForRegex("~", &out)); // ~ == 0x7E == 126
+ EXPECT_FALSE(
+ Sandbox::QuoteStringForRegex(WideToUTF8(L"^\u2135.\u2136$"), &out));
}
{
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(regex_cases); ++i) {
std::string out;
std::string in = WideToUTF8(regex_cases[i].to_escape);
- EXPECT_TRUE(QuoteStringForRegex(in, &out));
+ EXPECT_TRUE(Sandbox::QuoteStringForRegex(in, &out));
std::string expected("^");
expected.append(regex_cases[i].escaped);
expected.append(kSandboxEscapeSuffix);
@@ -125,7 +120,7 @@ TEST_F(MacDirAccessSandboxTest, RegexEscape) {
expected.append(kSandboxEscapeSuffix);
std::string out;
- EXPECT_TRUE(QuoteStringForRegex(in_utf8, &out));
+ EXPECT_TRUE(Sandbox::QuoteStringForRegex(in_utf8, &out));
EXPECT_EQ(expected, out);
}
@@ -143,14 +138,15 @@ class ScopedDirectoryDelete {
typedef scoped_ptr_malloc<FilePath, ScopedDirectoryDelete> ScopedDirectory;
-// Crashy, http://crbug.com/56765.
-TEST_F(MacDirAccessSandboxTest, DISABLED_SandboxAccess) {
+TEST_F(MacDirAccessSandboxTest, SandboxAccess) {
+ using file_util::CreateDirectory;
+
FilePath tmp_dir;
ASSERT_TRUE(file_util::CreateNewTempDirectory("", &tmp_dir));
// This step is important on OS X since the sandbox only understands "real"
// paths and the paths CreateNewTempDirectory() returns are empirically in
// /var which is a symlink to /private/var .
- sandbox::GetCanonicalSandboxPath(&tmp_dir);
+ Sandbox::GetCanonicalSandboxPath(&tmp_dir);
ScopedDirectory cleanup(&tmp_dir);
const char* sandbox_dir_cases[] = {
@@ -162,8 +158,18 @@ TEST_F(MacDirAccessSandboxTest, DISABLED_SandboxAccess) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(sandbox_dir_cases); ++i) {
const char* sandbox_dir_name = sandbox_dir_cases[i];
FilePath sandbox_dir = tmp_dir.Append(sandbox_dir_name);
- ASSERT_TRUE(file_util::CreateDirectory(sandbox_dir));
+ ASSERT_TRUE(CreateDirectory(sandbox_dir));
ScopedDirectory cleanup_sandbox(&sandbox_dir);
+
+ // Create a sibling directory of the sandbox dir, whose name has sandbox dir
+ // as a substring but to which access is denied.
+ std::string sibling_sandbox_dir_name_denied =
+ std::string(sandbox_dir_cases[i]) + kDeniedSuffix;
+ FilePath sibling_sandbox_dir = tmp_dir.Append(
+ sibling_sandbox_dir_name_denied.c_str());
+ ASSERT_TRUE(CreateDirectory(sibling_sandbox_dir));
+ ScopedDirectory cleanup_sandbox_sibling(&sibling_sandbox_dir);
+
EXPECT_TRUE(CheckSandbox(sandbox_dir.value()));
}
}
@@ -173,29 +179,36 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
if (!sandbox_allowed_dir)
return -1;
- // Build up a sandbox profile that only allows access to DIR_TO_ALLOW_ACCESS.
+ // Build up a sandbox profile that only allows access to a single directory.
NSString *sandbox_profile =
@"(version 1)" \
"(deny default)" \
"(allow signal (target self))" \
"(allow sysctl-read)" \
- "(allow file-read-metadata)" \
- "(allow file-read* file-write* (regex #\"DIR_TO_ALLOW_ACCESS\"))";
+ ";ENABLE_DIRECTORY_ACCESS";
std::string allowed_dir(sandbox_allowed_dir);
- std::string allowed_dir_escaped;
- if (!sandbox::QuoteStringForRegex(allowed_dir, &allowed_dir_escaped)) {
- LOG(ERROR) << "Regex string quoting failed " << allowed_dir;
+ Sandbox::SandboxVariableSubstitions substitutions;
+ NSString* allow_dir_sandbox_code =
+ Sandbox::BuildAllowDirectoryAccessSandboxString(
+ FilePath(sandbox_allowed_dir),
+ &substitutions);
+ sandbox_profile = [sandbox_profile
+ stringByReplacingOccurrencesOfString:@";ENABLE_DIRECTORY_ACCESS"
+ withString:allow_dir_sandbox_code];
+
+ std::string final_sandbox_profile_str;
+ if (!Sandbox::PostProcessSandboxProfile(sandbox_profile,
+ [NSArray array],
+ substitutions,
+ &final_sandbox_profile_str)) {
+ LOG(ERROR) << "Call to PostProcessSandboxProfile() failed";
return -1;
}
- NSString* allowed_dir_escaped_ns = base::SysUTF8ToNSString(
- allowed_dir_escaped.c_str());
- sandbox_profile = [sandbox_profile
- stringByReplacingOccurrencesOfString:@"DIR_TO_ALLOW_ACCESS"
- withString:allowed_dir_escaped_ns];
+
// Enable Sandbox.
char* error_buff = NULL;
- int error = sandbox_init([sandbox_profile UTF8String], 0, &error_buff);
+ int error = sandbox_init(final_sandbox_profile_str.c_str(), 0, &error_buff);
if (error == -1) {
LOG(ERROR) << "Failed to Initialize Sandbox: " << error_buff;
return -1;
@@ -223,8 +236,9 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
// Try to write a file who's name has the same prefix as the directory we
// allow access to.
FilePath basename = allowed_dir_path.BaseName();
+ FilePath allowed_parent_dir = allowed_dir_path.DirName();
std::string tricky_filename = basename.value() + "123";
- FilePath denied_file2 = allowed_dir_path.DirName().Append(tricky_filename);
+ FilePath denied_file2 = allowed_parent_dir.Append(tricky_filename);
if (open(allowed_file.value().c_str(), O_WRONLY | O_CREAT) <= 0) {
PLOG(ERROR) << "Sandbox overly restrictive: failed to write ("
@@ -233,6 +247,43 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
return -1;
}
+ // Test that we deny access to a sibling of the sandboxed directory whose
+ // name has the sandboxed directory name as a substring. e.g. if the sandbox
+ // directory is /foo/baz then test /foo/baz_denied.
+ {
+ struct stat tmp_stat_info;
+ std::string denied_sibling =
+ std::string(sandbox_allowed_dir) + kDeniedSuffix;
+ if (stat(denied_sibling.c_str(), &tmp_stat_info) > 0) {
+ PLOG(ERROR) << "Sandbox breach: was able to stat ("
+ << denied_sibling.c_str()
+ << ")";
+ return -1;
+ }
+ }
+
+ // Test that we can stat parent directories of the "allowed" directory.
+ {
+ struct stat tmp_stat_info;
+ if (stat(allowed_parent_dir.value().c_str(), &tmp_stat_info) != 0) {
+ PLOG(ERROR) << "Sandbox overly restrictive: unable to stat ("
+ << allowed_parent_dir.value()
+ << ")";
+ return -1;
+ }
+ }
+
+ // Test that we can't stat files outside the "allowed" directory.
+ {
+ struct stat tmp_stat_info;
+ if (stat(denied_file1.value().c_str(), &tmp_stat_info) > 0) {
+ PLOG(ERROR) << "Sandbox breach: was able to stat ("
+ << denied_file1.value()
+ << ")";
+ return -1;
+ }
+ }
+
if (open(denied_file1.value().c_str(), O_WRONLY | O_CREAT) > 0) {
PLOG(ERROR) << "Sandbox breach: was able to write ("
<< denied_file1.value()
@@ -250,4 +301,4 @@ MULTIPROCESS_TEST_MAIN(mac_sandbox_path_access) {
return 0;
}
-} // namespace
+} // namespace sandbox