Index: sandbox/linux/syscall_broker/broker_file_permission_unittest.cc |
diff --git a/sandbox/linux/syscall_broker/broker_file_permission_unittest.cc b/sandbox/linux/syscall_broker/broker_file_permission_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2853021448db8f086ff1ba4596805e48ffdce377 |
--- /dev/null |
+++ b/sandbox/linux/syscall_broker/broker_file_permission_unittest.cc |
@@ -0,0 +1,262 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "sandbox/linux/syscall_broker/broker_file_permission.h" |
+ |
+#include <fcntl.h> |
+#include <string.h> |
+#include <sys/stat.h> |
+#include <sys/types.h> |
+#include <unistd.h> |
+ |
+#include "base/logging.h" |
+#include "base/macros.h" |
+#include "sandbox/linux/tests/test_utils.h" |
+#include "sandbox/linux/tests/unit_tests.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace sandbox { |
+ |
+namespace syscall_broker { |
+ |
+class BrokerFilePermissionTester { |
+ public: |
+ static bool ValidatePath(const char* path) { |
+ return BrokerFilePermission::ValidatePath(path); |
+ } |
+ static const char* GetErrorMessage() { |
+ return BrokerFilePermission::GetErrorMessageForTests(); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(BrokerFilePermissionTester); |
+}; |
+ |
+namespace { |
+ |
+// Creation tests are DEATH tests as a bad permission causes termination. |
+SANDBOX_TEST(BrokerFilePermission, CreateGood) { |
+ const char kPath[] = "/tmp/good"; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadOnly(kPath); |
+} |
+ |
+SANDBOX_TEST(BrokerFilePermission, CreateGoodRecursive) { |
+ const char kPath[] = "/tmp/good/"; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadOnlyRecursive(kPath); |
+} |
+ |
+SANDBOX_DEATH_TEST( |
+ BrokerFilePermission, |
+ CreateBad, |
+ DEATH_MESSAGE(BrokerFilePermissionTester::GetErrorMessage())) { |
+ const char kPath[] = "/tmp/bad/"; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadOnly(kPath); |
+} |
+ |
+SANDBOX_DEATH_TEST( |
+ BrokerFilePermission, |
+ CreateBadRecursive, |
+ DEATH_MESSAGE(BrokerFilePermissionTester::GetErrorMessage())) { |
+ const char kPath[] = "/tmp/bad"; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadOnlyRecursive(kPath); |
+} |
+ |
+SANDBOX_DEATH_TEST( |
+ BrokerFilePermission, |
+ CreateBadNotAbs, |
+ DEATH_MESSAGE(BrokerFilePermissionTester::GetErrorMessage())) { |
+ const char kPath[] = "tmp/bad"; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadOnly(kPath); |
+} |
+ |
+SANDBOX_DEATH_TEST( |
+ BrokerFilePermission, |
+ CreateBadEmpty, |
+ DEATH_MESSAGE(BrokerFilePermissionTester::GetErrorMessage())) { |
+ const char kPath[] = ""; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadOnly(kPath); |
+} |
+ |
+// CheckPerm tests |path| against |perm| given |access_flags|. |
+// If |create| is true then file creation is tested for success. |
+void CheckPerm(const BrokerFilePermission& perm, |
+ const char* path, |
+ int access_flags, |
+ bool create) { |
+ const char* file_to_open = NULL; |
+ |
+ ASSERT_FALSE(perm.CheckAccess(path, X_OK, NULL)); |
+ ASSERT_TRUE(perm.CheckAccess(path, F_OK, NULL)); |
+ // check bad perms |
+ switch (access_flags) { |
+ case O_RDONLY: |
+ ASSERT_TRUE(perm.CheckOpen(path, O_RDONLY, &file_to_open, NULL)); |
+ ASSERT_FALSE(perm.CheckOpen(path, O_WRONLY, &file_to_open, NULL)); |
+ ASSERT_FALSE(perm.CheckOpen(path, O_RDWR, &file_to_open, NULL)); |
+ ASSERT_TRUE(perm.CheckAccess(path, R_OK, NULL)); |
+ ASSERT_FALSE(perm.CheckAccess(path, W_OK, NULL)); |
+ break; |
+ case O_WRONLY: |
+ ASSERT_FALSE(perm.CheckOpen(path, O_RDONLY, &file_to_open, NULL)); |
+ ASSERT_TRUE(perm.CheckOpen(path, O_WRONLY, &file_to_open, NULL)); |
+ ASSERT_FALSE(perm.CheckOpen(path, O_RDWR, &file_to_open, NULL)); |
+ ASSERT_FALSE(perm.CheckAccess(path, R_OK, NULL)); |
+ ASSERT_TRUE(perm.CheckAccess(path, W_OK, NULL)); |
+ break; |
+ case O_RDWR: |
+ ASSERT_TRUE(perm.CheckOpen(path, O_RDONLY, &file_to_open, NULL)); |
+ ASSERT_TRUE(perm.CheckOpen(path, O_WRONLY, &file_to_open, NULL)); |
+ ASSERT_TRUE(perm.CheckOpen(path, O_RDWR, &file_to_open, NULL)); |
+ ASSERT_TRUE(perm.CheckAccess(path, R_OK, NULL)); |
+ ASSERT_TRUE(perm.CheckAccess(path, W_OK, NULL)); |
+ break; |
+ default: |
+ // Bad test case |
+ NOTREACHED(); |
+ } |
+ |
+// O_SYNC can be defined as (__O_SYNC|O_DSYNC) |
+#ifdef O_DSYNC |
+ const int kSyncFlag = O_SYNC & ~O_DSYNC; |
+#else |
+ const int kSyncFlag = O_SYNC; |
+#endif |
+ |
+ const int kNumberOfBitsInOAccMode = 2; |
+ COMPILE_ASSERT(O_ACCMODE == ((1 << kNumberOfBitsInOAccMode) - 1), |
+ number_of_bits); |
+ // check every possible flag and act accordingly. |
+ // Skipping AccMode bits as they are present in every case. |
+ for (int i = kNumberOfBitsInOAccMode; i < 32; i++) { |
+ int flag = 1 << i; |
+ switch (flag) { |
+ case O_APPEND: |
+ case O_ASYNC: |
+ case O_DIRECT: |
+ case O_DIRECTORY: |
+#ifdef O_DSYNC |
+ case O_DSYNC: |
+#endif |
+ case O_EXCL: |
+ case O_LARGEFILE: |
+ case O_NOATIME: |
+ case O_NOCTTY: |
+ case O_NOFOLLOW: |
+ case O_NONBLOCK: |
+#if (O_NONBLOCK != O_NDELAY) |
+ case O_NDELAY: |
+#endif |
+ case kSyncFlag: |
+ case O_TRUNC: |
+ ASSERT_TRUE( |
+ perm.CheckOpen(path, access_flags | flag, &file_to_open, NULL)); |
+ break; |
+ case O_CLOEXEC: |
+ case O_CREAT: |
+ default: |
+ ASSERT_FALSE( |
+ perm.CheckOpen(path, access_flags | flag, &file_to_open, NULL)); |
+ } |
+ } |
+ if (create) { |
+ bool unlink; |
+ ASSERT_TRUE(perm.CheckOpen(path, O_CREAT | O_EXCL | access_flags, |
+ &file_to_open, &unlink)); |
+ ASSERT_FALSE(unlink); |
+ } else { |
+ ASSERT_FALSE(perm.CheckOpen(path, O_CREAT | O_EXCL | access_flags, |
+ &file_to_open, NULL)); |
+ } |
+} |
+ |
+TEST(BrokerFilePermission, ReadOnly) { |
+ const char kPath[] = "/tmp/good"; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadOnly(kPath); |
+ CheckPerm(perm, kPath, O_RDONLY, false); |
+ // Don't do anything here, so that ASSERT works in the subfunction as |
+ // expected. |
+} |
+ |
+TEST(BrokerFilePermission, ReadOnlyRecursive) { |
+ const char kPath[] = "/tmp/good/"; |
+ const char kPathFile[] = "/tmp/good/file"; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadOnlyRecursive(kPath); |
+ CheckPerm(perm, kPathFile, O_RDONLY, false); |
+ // Don't do anything here, so that ASSERT works in the subfunction as |
+ // expected. |
+} |
+ |
+TEST(BrokerFilePermission, WriteOnly) { |
+ const char kPath[] = "/tmp/good"; |
+ BrokerFilePermission perm = BrokerFilePermission::WriteOnly(kPath); |
+ CheckPerm(perm, kPath, O_WRONLY, false); |
+ // Don't do anything here, so that ASSERT works in the subfunction as |
+ // expected. |
+} |
+ |
+TEST(BrokerFilePermission, ReadWrite) { |
+ const char kPath[] = "/tmp/good"; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadWrite(kPath); |
+ CheckPerm(perm, kPath, O_RDWR, false); |
+ // Don't do anything here, so that ASSERT works in the subfunction as |
+ // expected. |
+} |
+ |
+TEST(BrokerFilePermission, ReadWriteCreate) { |
+ const char kPath[] = "/tmp/good"; |
+ BrokerFilePermission perm = BrokerFilePermission::ReadWriteCreate(kPath); |
+ CheckPerm(perm, kPath, O_RDWR, true); |
+ // Don't do anything here, so that ASSERT works in the subfunction as |
+ // expected. |
+} |
+ |
+void CheckUnlink(BrokerFilePermission& perm, |
+ const char* path, |
+ int access_flags) { |
+ bool unlink; |
+ ASSERT_FALSE(perm.CheckOpen(path, access_flags, NULL, &unlink)); |
+ ASSERT_FALSE(perm.CheckOpen(path, access_flags | O_CREAT, NULL, &unlink)); |
+ ASSERT_TRUE( |
+ perm.CheckOpen(path, access_flags | O_CREAT | O_EXCL, NULL, &unlink)); |
+ ASSERT_TRUE(unlink); |
+} |
+ |
+TEST(BrokerFilePermission, ReadWriteCreateUnlink) { |
+ const char kPath[] = "/tmp/good"; |
+ BrokerFilePermission perm = |
+ BrokerFilePermission::ReadWriteCreateUnlink(kPath); |
+ CheckUnlink(perm, kPath, O_RDWR); |
+ // Don't do anything here, so that ASSERT works in the subfunction as |
+ // expected. |
+} |
+ |
+TEST(BrokerFilePermission, ReadWriteCreateUnlinkRecursive) { |
+ const char kPath[] = "/tmp/good/"; |
+ const char kPathFile[] = "/tmp/good/file"; |
+ BrokerFilePermission perm = |
+ BrokerFilePermission::ReadWriteCreateUnlinkRecursive(kPath); |
+ CheckUnlink(perm, kPathFile, O_RDWR); |
+ // Don't do anything here, so that ASSERT works in the subfunction as |
+ // expected. |
+} |
+ |
+TEST(BrokerFilePermission, ValidatePath) { |
+ EXPECT_TRUE(BrokerFilePermissionTester::ValidatePath("/path")); |
+ EXPECT_TRUE(BrokerFilePermissionTester::ValidatePath("/")); |
+ EXPECT_TRUE(BrokerFilePermissionTester::ValidatePath("/..path")); |
+ |
+ EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("")); |
+ EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("bad")); |
+ EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("/bad/")); |
+ EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("bad/")); |
+ EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("/bad/..")); |
+ EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("/bad/../bad")); |
+ EXPECT_FALSE(BrokerFilePermissionTester::ValidatePath("/../bad")); |
+} |
+ |
+} // namespace |
+ |
+} // namespace syscall_broker |
+ |
+} // namespace sandbox |