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