Chromium Code Reviews| 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..8f5e2d5bb6466cd63d095ec74e965c48287d7402 |
| --- /dev/null |
| +++ b/sandbox/linux/syscall_broker/broker_file_permission_unittest.cc |
| @@ -0,0 +1,243 @@ |
| +// 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 "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 |
| + |
| + // check every possible flag and act accordingly. |
| + for (int i = 2; 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); // CheckPerm must be last |
|
jln (very slow on Chromium)
2014/11/26 19:49:06
Explain why: "For ASSERT* to successfully exit the
|
| +} |
| + |
| +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); // CheckPerm must be last |
| +} |
| + |
| +TEST(BrokerFilePermission, WriteOnly) { |
| + const char kPath[] = "/tmp/good"; |
| + BrokerFilePermission perm = BrokerFilePermission::WriteOnly(kPath); |
| + CheckPerm(perm, kPath, O_WRONLY, false); // CheckPerm must be last |
| +} |
| + |
| +TEST(BrokerFilePermission, ReadWrite) { |
| + const char kPath[] = "/tmp/good"; |
| + BrokerFilePermission perm = BrokerFilePermission::ReadWrite(kPath); |
| + CheckPerm(perm, kPath, O_RDWR, false); // CheckPerm must be last |
| +} |
| + |
| +TEST(BrokerFilePermission, ReadWriteCreate) { |
| + const char kPath[] = "/tmp/good"; |
| + BrokerFilePermission perm = BrokerFilePermission::ReadWriteCreate(kPath); |
| + CheckPerm(perm, kPath, O_RDWR, true); // CheckPerm must be last |
| +} |
| + |
| +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); // CheckUnlink must be last |
| +} |
| + |
| +TEST(BrokerFilePermission, ReadWriteCreateUnlinkRecursive) { |
| + const char kPath[] = "/tmp/good/"; |
| + const char kPathFile[] = "/tmp/good/file"; |
| + BrokerFilePermission perm = |
| + BrokerFilePermission::ReadWriteCreateUnlinkRecursive(kPath); |
| + CheckUnlink(perm, kPathFile, O_RDWR); // CheckUnlink must be last |
| +} |
| + |
| +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 |