security/sandbox/win/src/file_policy_test.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #include <algorithm>
     6 #include <cctype>
     8 #include <windows.h>
     9 #include <winioctl.h>
    11 #include "base/win/scoped_handle.h"
    12 #include "sandbox/win/src/nt_internals.h"
    13 #include "sandbox/win/src/sandbox.h"
    14 #include "sandbox/win/src/sandbox_factory.h"
    15 #include "sandbox/win/src/sandbox_policy.h"
    16 #include "sandbox/win/src/win_utils.h"
    17 #include "sandbox/win/tests/common/controller.h"
    18 #include "sandbox/win/tests/common/test_utils.h"
    19 #include "testing/gtest/include/gtest/gtest.h"
    21 #define BINDNTDLL(name) \
    22   name ## Function name = reinterpret_cast<name ## Function>( \
    23     ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name))
    25 namespace sandbox {
    27 const ULONG kSharing = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE;
    29 // Creates a file using different desired access. Returns if the call succeeded
    30 // or not.  The first argument in argv is the filename. If the second argument
    31 // is "read", we try read only access. Otherwise we try read-write access.
    32 SBOX_TESTS_COMMAND int File_Create(int argc, wchar_t **argv) {
    33   if (argc != 2)
    34     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
    36   bool read = (_wcsicmp(argv[0], L"Read") == 0);
    38   if (read) {
    39     base::win::ScopedHandle file1(CreateFile(
    40         argv[1], GENERIC_READ, kSharing, NULL, OPEN_EXISTING, 0, NULL));
    41     base::win::ScopedHandle file2(CreateFile(
    42         argv[1], FILE_EXECUTE, kSharing, NULL, OPEN_EXISTING, 0, NULL));
    44     if (file1.Get() && file2.Get())
    45       return SBOX_TEST_SUCCEEDED;
    46     return SBOX_TEST_DENIED;
    47   } else {
    48     base::win::ScopedHandle file1(CreateFile(
    49         argv[1], GENERIC_ALL, kSharing, NULL, OPEN_EXISTING, 0, NULL));
    50     base::win::ScopedHandle file2(CreateFile(
    51         argv[1], GENERIC_READ | FILE_WRITE_DATA, kSharing, NULL, OPEN_EXISTING,
    52         0, NULL));
    54     if (file1.Get() && file2.Get())
    55       return SBOX_TEST_SUCCEEDED;
    56     return SBOX_TEST_DENIED;
    57   }
    58 }
    60 SBOX_TESTS_COMMAND int File_Win32Create(int argc, wchar_t **argv) {
    61   if (argc != 1) {
    62     SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
    63   }
    65   std::wstring full_path = MakePathToSys(argv[0], false);
    66   if (full_path.empty()) {
    67     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
    68   }
    70   HANDLE file = ::CreateFileW(full_path.c_str(), GENERIC_READ, kSharing,
    71                               NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    73   if (INVALID_HANDLE_VALUE != file) {
    74     ::CloseHandle(file);
    75     return SBOX_TEST_SUCCEEDED;
    76   } else {
    77     if (ERROR_ACCESS_DENIED == ::GetLastError()) {
    78       return SBOX_TEST_DENIED;
    79     } else {
    80       return SBOX_TEST_FAILED;
    81     }
    82   }
    83   return SBOX_TEST_SUCCEEDED;
    84 }
    86 // Creates the file in parameter using the NtCreateFile api and returns if the
    87 // call succeeded or not.
    88 SBOX_TESTS_COMMAND int File_CreateSys32(int argc, wchar_t **argv) {
    89   BINDNTDLL(NtCreateFile);
    90   BINDNTDLL(RtlInitUnicodeString);
    91   if (!NtCreateFile || !RtlInitUnicodeString)
    92     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
    94   if (argc != 1)
    95     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
    97   std::wstring file(argv[0]);
    98   if (0 != _wcsnicmp(file.c_str(), kNTObjManPrefix, kNTObjManPrefixLen))
    99     file = MakePathToSys(argv[0], true);
   101   UNICODE_STRING object_name;
   102   RtlInitUnicodeString(&object_name, file.c_str());
   104   OBJECT_ATTRIBUTES obj_attributes = {0};
   105   InitializeObjectAttributes(&obj_attributes, &object_name,
   106                              OBJ_CASE_INSENSITIVE, NULL, NULL);
   108   HANDLE handle;
   109   IO_STATUS_BLOCK io_block = {0};
   110   NTSTATUS status = NtCreateFile(&handle, FILE_READ_DATA, &obj_attributes,
   111                                  &io_block, NULL, 0, kSharing, FILE_OPEN,
   112                                  0, NULL, 0);
   113   if (NT_SUCCESS(status)) {
   114     ::CloseHandle(handle);
   115     return SBOX_TEST_SUCCEEDED;
   116   } else if (STATUS_ACCESS_DENIED == status) {
   117     return SBOX_TEST_DENIED;
   118   } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) {
   119     return SBOX_TEST_NOT_FOUND;
   120   }
   121   return SBOX_TEST_FAILED;
   122 }
   124 // Opens the file in parameter using the NtOpenFile api and returns if the
   125 // call succeeded or not.
   126 SBOX_TESTS_COMMAND int File_OpenSys32(int argc, wchar_t **argv) {
   127   BINDNTDLL(NtOpenFile);
   128   BINDNTDLL(RtlInitUnicodeString);
   129   if (!NtOpenFile || !RtlInitUnicodeString)
   130     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
   132   if (argc != 1)
   133     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
   135   std::wstring file = MakePathToSys(argv[0], true);
   136   UNICODE_STRING object_name;
   137   RtlInitUnicodeString(&object_name, file.c_str());
   139   OBJECT_ATTRIBUTES obj_attributes = {0};
   140   InitializeObjectAttributes(&obj_attributes, &object_name,
   141                              OBJ_CASE_INSENSITIVE, NULL, NULL);
   143   HANDLE handle;
   144   IO_STATUS_BLOCK io_block = {0};
   145   NTSTATUS status = NtOpenFile(&handle, FILE_READ_DATA, &obj_attributes,
   146                                &io_block, kSharing, 0);
   147   if (NT_SUCCESS(status)) {
   148     ::CloseHandle(handle);
   149     return SBOX_TEST_SUCCEEDED;
   150   } else if (STATUS_ACCESS_DENIED == status) {
   151     return SBOX_TEST_DENIED;
   152   } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) {
   153     return SBOX_TEST_NOT_FOUND;
   154   }
   155   return SBOX_TEST_FAILED;
   156 }
   158 SBOX_TESTS_COMMAND int File_GetDiskSpace(int argc, wchar_t **argv) {
   159   std::wstring sys_path = MakePathToSys(L"", false);
   160   if (sys_path.empty()) {
   161     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
   162   }
   163   ULARGE_INTEGER free_user = {0};
   164   ULARGE_INTEGER total = {0};
   165   ULARGE_INTEGER free_total = {0};
   166   if (::GetDiskFreeSpaceExW(sys_path.c_str(), &free_user, &total,
   167                             &free_total)) {
   168     if ((total.QuadPart != 0) && (free_total.QuadPart !=0)) {
   169       return SBOX_TEST_SUCCEEDED;
   170     }
   171   } else {
   172     if (ERROR_ACCESS_DENIED == ::GetLastError()) {
   173       return SBOX_TEST_DENIED;
   174     } else {
   175       return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
   176     }
   177   }
   178   return SBOX_TEST_SUCCEEDED;
   179 }
   181 // Move a file using the MoveFileEx api and returns if the call succeeded or
   182 // not.
   183 SBOX_TESTS_COMMAND int File_Rename(int argc, wchar_t **argv) {
   184   if (argc != 2)
   185     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
   187   if (::MoveFileEx(argv[0], argv[1], 0))
   188     return SBOX_TEST_SUCCEEDED;
   190   if (::GetLastError() != ERROR_ACCESS_DENIED)
   191     return SBOX_TEST_FAILED;
   193   return SBOX_TEST_DENIED;
   194 }
   196 // Query the attributes of file in parameter using the NtQueryAttributesFile api
   197 // and NtQueryFullAttributesFile and returns if the call succeeded or not. The
   198 // second argument in argv is "d" or "f" telling if we expect the attributes to
   199 // specify a file or a directory. The expected attribute has to match the real
   200 // attributes for the call to be successful.
   201 SBOX_TESTS_COMMAND int File_QueryAttributes(int argc, wchar_t **argv) {
   202   BINDNTDLL(NtQueryAttributesFile);
   203   BINDNTDLL(NtQueryFullAttributesFile);
   204   BINDNTDLL(RtlInitUnicodeString);
   205   if (!NtQueryAttributesFile || !NtQueryFullAttributesFile ||
   206       !RtlInitUnicodeString)
   207     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
   209   if (argc != 2)
   210     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
   212   bool expect_directory = (L'd' == argv[1][0]);
   214   UNICODE_STRING object_name;
   215   std::wstring file = MakePathToSys(argv[0], true);
   216   RtlInitUnicodeString(&object_name, file.c_str());
   218   OBJECT_ATTRIBUTES obj_attributes = {0};
   219   InitializeObjectAttributes(&obj_attributes, &object_name,
   220                              OBJ_CASE_INSENSITIVE, NULL, NULL);
   222   FILE_BASIC_INFORMATION info = {0};
   223   FILE_NETWORK_OPEN_INFORMATION full_info = {0};
   224   NTSTATUS status1 = NtQueryAttributesFile(&obj_attributes, &info);
   225   NTSTATUS status2 = NtQueryFullAttributesFile(&obj_attributes, &full_info);
   227   if (status1 != status2)
   228     return SBOX_TEST_FAILED;
   230   if (NT_SUCCESS(status1)) {
   231     if (info.FileAttributes != full_info.FileAttributes)
   232       return SBOX_TEST_FAILED;
   234     bool is_directory1 = (info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
   235     if (expect_directory == is_directory1)
   236       return SBOX_TEST_SUCCEEDED;
   237   } else if (STATUS_ACCESS_DENIED == status1) {
   238     return SBOX_TEST_DENIED;
   239   } else if (STATUS_OBJECT_NAME_NOT_FOUND == status1) {
   240     return SBOX_TEST_NOT_FOUND;
   241   }
   243   return SBOX_TEST_FAILED;
   244 }
   246 TEST(FilePolicyTest, DenyNtCreateCalc) {
   247   TestRunner runner;
   248   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY,
   249                                   L"calc.exe"));
   251   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 calc.exe"));
   253   runner.SetTestState(BEFORE_REVERT);
   254   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
   255 }
   257 TEST(FilePolicyTest, AllowNtCreateCalc) {
   258   TestRunner runner;
   259   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.exe"));
   261   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
   263   runner.SetTestState(BEFORE_REVERT);
   264   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
   265 }
   267 TEST(FilePolicyTest, AllowNtCreateWithNativePath) {
   268   std::wstring calc = MakePathToSys(L"calc.exe", false);
   269   std::wstring nt_path;
   270   ASSERT_TRUE(GetNtPathFromWin32Path(calc, &nt_path));
   271   TestRunner runner;
   272   runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, nt_path.c_str());
   274   wchar_t buff[MAX_PATH];
   275   ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
   276   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
   278   std::transform(nt_path.begin(), nt_path.end(), nt_path.begin(), std::tolower);
   279   ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
   280   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
   281 }
   283 TEST(FilePolicyTest, AllowReadOnly) {
   284   TestRunner runner;
   286   // Create a temp file because we need write access to it.
   287   wchar_t temp_directory[MAX_PATH];
   288   wchar_t temp_file_name[MAX_PATH];
   289   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
   290   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
   292   EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
   293                                temp_file_name));
   295   wchar_t command_read[MAX_PATH + 20] = {0};
   296   wsprintf(command_read, L"File_Create Read \"%ls\"", temp_file_name);
   297   wchar_t command_write[MAX_PATH + 20] = {0};
   298   wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name);
   300   // Verify that we have read access after revert.
   301   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_read));
   303   // Verify that we don't have write access after revert.
   304   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write));
   306   // Verify that we really have write access to the file.
   307   runner.SetTestState(BEFORE_REVERT);
   308   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write));
   310   DeleteFile(temp_file_name);
   311 }
   313 TEST(FilePolicyTest, AllowWildcard) {
   314   TestRunner runner;
   316   // Create a temp file because we need write access to it.
   317   wchar_t temp_directory[MAX_PATH];
   318   wchar_t temp_file_name[MAX_PATH];
   319   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
   320   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
   322   wcscat_s(temp_directory, MAX_PATH, L"*");
   323   EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_directory));
   325   wchar_t command_write[MAX_PATH + 20] = {0};
   326   wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name);
   328   // Verify that we have write access after revert.
   329   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write));
   331   DeleteFile(temp_file_name);
   332 }
   334 TEST(FilePolicyTest, AllowNtCreatePatternRule) {
   335   TestRunner runner;
   336   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"App*.dll"));
   338   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
   339             runner.RunTest(L"File_OpenSys32 appmgmts.dll"));
   340   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
   342   runner.SetTestState(BEFORE_REVERT);
   343   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
   344             runner.RunTest(L"File_OpenSys32 appmgmts.dll"));
   345   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
   346 }
   348 TEST(FilePolicyTest, CheckNotFound) {
   349   TestRunner runner;
   350   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"n*.dll"));
   352   EXPECT_EQ(SBOX_TEST_NOT_FOUND,
   353             runner.RunTest(L"File_OpenSys32 notfound.dll"));
   354 }
   356 TEST(FilePolicyTest, CheckNoLeak) {
   357   TestRunner runner;
   358   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 notfound.exe"));
   359 }
   361 TEST(FilePolicyTest, TestQueryAttributesFile) {
   362   TestRunner runner;
   363   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY,
   364                                   L"appmgmts.dll"));
   365   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY,
   366                                   L"notfound.exe"));
   367   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"drivers"));
   368   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_QUERY,
   369                                   L"ipconfig.exe"));
   371   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
   372             runner.RunTest(L"File_QueryAttributes drivers d"));
   374   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
   375             runner.RunTest(L"File_QueryAttributes appmgmts.dll f"));
   377   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
   378             runner.RunTest(L"File_QueryAttributes ipconfig.exe f"));
   380   EXPECT_EQ(SBOX_TEST_DENIED,
   381             runner.RunTest(L"File_QueryAttributes ftp.exe f"));
   383   EXPECT_EQ(SBOX_TEST_NOT_FOUND,
   384             runner.RunTest(L"File_QueryAttributes notfound.exe f"));
   385 }
   387 // Makes sure that we don't leak information when there is not policy to allow
   388 // a path.
   389 TEST(FilePolicyTest, TestQueryAttributesFileNoPolicy) {
   390   TestRunner runner;
   391   EXPECT_EQ(SBOX_TEST_DENIED,
   392             runner.RunTest(L"File_QueryAttributes ftp.exe f"));
   394   EXPECT_EQ(SBOX_TEST_DENIED,
   395             runner.RunTest(L"File_QueryAttributes notfound.exe f"));
   396 }
   398 TEST(FilePolicyTest, TestRename) {
   399   TestRunner runner;
   401   // Give access to the temp directory.
   402   wchar_t temp_directory[MAX_PATH];
   403   wchar_t temp_file_name1[MAX_PATH];
   404   wchar_t temp_file_name2[MAX_PATH];
   405   wchar_t temp_file_name3[MAX_PATH];
   406   wchar_t temp_file_name4[MAX_PATH];
   407   wchar_t temp_file_name5[MAX_PATH];
   408   wchar_t temp_file_name6[MAX_PATH];
   409   wchar_t temp_file_name7[MAX_PATH];
   410   wchar_t temp_file_name8[MAX_PATH];
   411   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
   412   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name1), 0u);
   413   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name2), 0u);
   414   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name3), 0u);
   415   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name4), 0u);
   416   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name5), 0u);
   417   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name6), 0u);
   418   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name7), 0u);
   419   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name8), 0u);
   422   // Add rules to make file1->file2 succeed.
   423   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name1));
   424   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name2));
   426   // Add rules to make file3->file4 fail.
   427   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name3));
   428   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
   429                                temp_file_name4));
   431   // Add rules to make file5->file6 fail.
   432   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
   433                                temp_file_name5));
   434   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name6));
   436   // Add rules to make file7->no_pol_file fail.
   437   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name7));
   439   // Delete the files where the files are going to be renamed to.
   440   ::DeleteFile(temp_file_name2);
   441   ::DeleteFile(temp_file_name4);
   442   ::DeleteFile(temp_file_name6);
   443   ::DeleteFile(temp_file_name8);
   446   wchar_t command[MAX_PATH*2 + 20] = {0};
   447   wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name1,
   448            temp_file_name2);
   449   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command));
   451   wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name3,
   452            temp_file_name4);
   453   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
   455   wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name5,
   456            temp_file_name6);
   457   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
   459   wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name7,
   460            temp_file_name8);
   461   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
   464   // Delete all the files in case they are still there.
   465   ::DeleteFile(temp_file_name1);
   466   ::DeleteFile(temp_file_name2);
   467   ::DeleteFile(temp_file_name3);
   468   ::DeleteFile(temp_file_name4);
   469   ::DeleteFile(temp_file_name5);
   470   ::DeleteFile(temp_file_name6);
   471   ::DeleteFile(temp_file_name7);
   472   ::DeleteFile(temp_file_name8);
   473 }
   475 TEST(FilePolicyTest, OpenSys32FilesDenyBecauseOfDir) {
   476   TestRunner runner;
   477   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY,
   478                                   L"notepad.exe"));
   480   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe"));
   482   runner.SetTestState(BEFORE_REVERT);
   483   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
   484             runner.RunTest(L"File_Win32Create notepad.exe"));
   485 }
   487 TEST(FilePolicyTest, OpenSys32FilesAllowNotepad) {
   488   TestRunner runner;
   489   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY,
   490                                   L"notepad.exe"));
   492   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
   493             runner.RunTest(L"File_Win32Create notepad.exe"));
   495   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create calc.exe"));
   497   runner.SetTestState(BEFORE_REVERT);
   498   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
   499             runner.RunTest(L"File_Win32Create notepad.exe"));
   500   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_Win32Create calc.exe"));
   501 }
   503 TEST(FilePolicyTest, FileGetDiskSpace) {
   504   TestRunner runner;
   505   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_GetDiskSpace"));
   506   runner.SetTestState(BEFORE_REVERT);
   507   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
   509   // Add an 'allow' rule in the windows\system32 such that GetDiskFreeSpaceEx
   510   // succeeds (it does an NtOpenFile) but windows\system32\notepad.exe is
   511   // denied since there is no wild card in the rule.
   512   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, L""));
   513   runner.SetTestState(BEFORE_REVERT);
   514   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
   516   runner.SetTestState(AFTER_REVERT);
   517   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
   518   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe"));
   519 }
   521 // http://crbug.com/146944
   522 TEST(FilePolicyTest, DISABLED_TestReparsePoint) {
   523   TestRunner runner;
   525   // Create a temp file because we need write access to it.
   526   wchar_t temp_directory[MAX_PATH];
   527   wchar_t temp_file_name[MAX_PATH];
   528   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
   529   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
   531   // Delete the file and create a directory instead.
   532   ASSERT_TRUE(::DeleteFile(temp_file_name));
   533   ASSERT_TRUE(::CreateDirectory(temp_file_name, NULL));
   535   // Create a temporary file in the subfolder.
   536   std::wstring subfolder = temp_file_name;
   537   std::wstring temp_file_title = subfolder.substr(subfolder.rfind(L"\\") + 1);
   538   std::wstring temp_file = subfolder + L"\\file_" + temp_file_title;
   540   HANDLE file = ::CreateFile(temp_file.c_str(), FILE_ALL_ACCESS,
   541                              FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
   542                              CREATE_ALWAYS, 0, NULL);
   543   ASSERT_TRUE(INVALID_HANDLE_VALUE != file);
   544   ASSERT_TRUE(::CloseHandle(file));
   546   // Create a temporary file in the temp directory.
   547   std::wstring temp_dir = temp_directory;
   548   std::wstring temp_file_in_temp = temp_dir + L"file_" + temp_file_title;
   549   file = ::CreateFile(temp_file_in_temp.c_str(), FILE_ALL_ACCESS,
   550                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
   551                       CREATE_ALWAYS, 0, NULL);
   552   ASSERT_TRUE(file != NULL);
   553   ASSERT_TRUE(::CloseHandle(file));
   555   // Give write access to the temp directory.
   556   std::wstring temp_dir_wildcard = temp_dir + L"*";
   557   EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY,
   558                                temp_dir_wildcard.c_str()));
   560   // Prepare the command to execute.
   561   std::wstring command_write;
   562   command_write += L"File_Create Write \"";
   563   command_write += temp_file;
   564   command_write += L"\"";
   566   // Verify that we have write access to the original file
   567   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write.c_str()));
   569   // Replace the subfolder by a reparse point to %temp%.
   570   ::DeleteFile(temp_file.c_str());
   571   HANDLE dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS,
   572                             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
   573                             OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
   574   EXPECT_TRUE(INVALID_HANDLE_VALUE != dir);
   576   std::wstring temp_dir_nt;
   577   temp_dir_nt += L"\\??\\";
   578   temp_dir_nt += temp_dir;
   579   EXPECT_TRUE(SetReparsePoint(dir, temp_dir_nt.c_str()));
   580   EXPECT_TRUE(::CloseHandle(dir));
   582   // Try to open the file again.
   583   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write.c_str()));
   585   // Remove the reparse point.
   586   dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS,
   587                      FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
   588                      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
   589                      NULL);
   590   EXPECT_TRUE(INVALID_HANDLE_VALUE != dir);
   591   EXPECT_TRUE(DeleteReparsePoint(dir));
   592   EXPECT_TRUE(::CloseHandle(dir));
   594   // Cleanup.
   595   EXPECT_TRUE(::DeleteFile(temp_file_in_temp.c_str()));
   596   EXPECT_TRUE(::RemoveDirectory(subfolder.c_str()));
   597 }
   599 }  // namespace sandbox

mercurial