[Ozone-Gbm] Explicitly crash if trying software rendering on GBM
[chromium-blink-merge.git] / sandbox / win / src / file_policy_test.cc
blob199dd4c68d5928cdb0d04ab9872951a37ea510bc
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/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"
22 #define BINDNTDLL(name) \
23 name ## Function name = reinterpret_cast<name ## Function>( \
24 ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name))
26 namespace sandbox {
28 const ULONG kSharing = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE;
30 // Creates a file using different desired access. Returns if the call succeeded
31 // or not. The first argument in argv is the filename. The second argument
32 // determines the type of access and the dispositino of the file.
33 SBOX_TESTS_COMMAND int File_Create(int argc, wchar_t **argv) {
34 if (argc != 2)
35 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
37 std::wstring operation(argv[0]);
39 if (operation == L"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));
45 if (file1.IsValid() == file2.IsValid())
46 return file1.IsValid() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED;
47 return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR;
49 } else if (operation == L"Write") {
50 base::win::ScopedHandle file1(CreateFile(
51 argv[1], GENERIC_ALL, kSharing, NULL, OPEN_EXISTING, 0, NULL));
52 base::win::ScopedHandle file2(CreateFile(
53 argv[1], GENERIC_READ | FILE_WRITE_DATA, kSharing, NULL, OPEN_EXISTING,
54 0, NULL));
56 if (file1.IsValid() == file2.IsValid())
57 return file1.IsValid() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED;
58 return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR;
60 } else if (operation == L"ReadCreate") {
61 base::win::ScopedHandle file2(CreateFile(
62 argv[1], GENERIC_READ, kSharing, NULL, CREATE_NEW, 0, NULL));
63 base::win::ScopedHandle file1(CreateFile(
64 argv[1], GENERIC_READ, kSharing, NULL, CREATE_ALWAYS, 0, NULL));
66 if (file1.IsValid() == file2.IsValid())
67 return file1.IsValid() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED;
68 return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR;
71 return SBOX_TEST_INVALID_PARAMETER;
74 SBOX_TESTS_COMMAND int File_Win32Create(int argc, wchar_t **argv) {
75 if (argc != 1) {
76 SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
79 base::string16 full_path = MakePathToSys(argv[0], false);
80 if (full_path.empty()) {
81 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
84 HANDLE file = ::CreateFileW(full_path.c_str(), GENERIC_READ, kSharing,
85 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
87 if (INVALID_HANDLE_VALUE != file) {
88 ::CloseHandle(file);
89 return SBOX_TEST_SUCCEEDED;
90 } else {
91 if (ERROR_ACCESS_DENIED == ::GetLastError()) {
92 return SBOX_TEST_DENIED;
93 } else {
94 return SBOX_TEST_FAILED;
97 return SBOX_TEST_SUCCEEDED;
100 // Creates the file in parameter using the NtCreateFile api and returns if the
101 // call succeeded or not.
102 SBOX_TESTS_COMMAND int File_CreateSys32(int argc, wchar_t **argv) {
103 BINDNTDLL(NtCreateFile);
104 BINDNTDLL(RtlInitUnicodeString);
105 if (!NtCreateFile || !RtlInitUnicodeString)
106 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
108 if (argc != 1)
109 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
111 base::string16 file(argv[0]);
112 if (0 != _wcsnicmp(file.c_str(), kNTObjManPrefix, kNTObjManPrefixLen))
113 file = MakePathToSys(argv[0], true);
115 UNICODE_STRING object_name;
116 RtlInitUnicodeString(&object_name, file.c_str());
118 OBJECT_ATTRIBUTES obj_attributes = {0};
119 InitializeObjectAttributes(&obj_attributes, &object_name,
120 OBJ_CASE_INSENSITIVE, NULL, NULL);
122 HANDLE handle;
123 IO_STATUS_BLOCK io_block = {0};
124 NTSTATUS status = NtCreateFile(&handle, FILE_READ_DATA, &obj_attributes,
125 &io_block, NULL, 0, kSharing, FILE_OPEN,
126 0, NULL, 0);
127 if (NT_SUCCESS(status)) {
128 ::CloseHandle(handle);
129 return SBOX_TEST_SUCCEEDED;
130 } else if (STATUS_ACCESS_DENIED == status) {
131 return SBOX_TEST_DENIED;
132 } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) {
133 return SBOX_TEST_NOT_FOUND;
135 return SBOX_TEST_FAILED;
138 // Opens the file in parameter using the NtOpenFile api and returns if the
139 // call succeeded or not.
140 SBOX_TESTS_COMMAND int File_OpenSys32(int argc, wchar_t **argv) {
141 BINDNTDLL(NtOpenFile);
142 BINDNTDLL(RtlInitUnicodeString);
143 if (!NtOpenFile || !RtlInitUnicodeString)
144 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
146 if (argc != 1)
147 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
149 base::string16 file = MakePathToSys(argv[0], true);
150 UNICODE_STRING object_name;
151 RtlInitUnicodeString(&object_name, file.c_str());
153 OBJECT_ATTRIBUTES obj_attributes = {0};
154 InitializeObjectAttributes(&obj_attributes, &object_name,
155 OBJ_CASE_INSENSITIVE, NULL, NULL);
157 HANDLE handle;
158 IO_STATUS_BLOCK io_block = {0};
159 NTSTATUS status = NtOpenFile(&handle, FILE_READ_DATA, &obj_attributes,
160 &io_block, kSharing, 0);
161 if (NT_SUCCESS(status)) {
162 ::CloseHandle(handle);
163 return SBOX_TEST_SUCCEEDED;
164 } else if (STATUS_ACCESS_DENIED == status) {
165 return SBOX_TEST_DENIED;
166 } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) {
167 return SBOX_TEST_NOT_FOUND;
169 return SBOX_TEST_FAILED;
172 SBOX_TESTS_COMMAND int File_GetDiskSpace(int argc, wchar_t **argv) {
173 base::string16 sys_path = MakePathToSys(L"", false);
174 if (sys_path.empty()) {
175 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
177 ULARGE_INTEGER free_user = {0};
178 ULARGE_INTEGER total = {0};
179 ULARGE_INTEGER free_total = {0};
180 if (::GetDiskFreeSpaceExW(sys_path.c_str(), &free_user, &total,
181 &free_total)) {
182 if ((total.QuadPart != 0) && (free_total.QuadPart !=0)) {
183 return SBOX_TEST_SUCCEEDED;
185 } else {
186 if (ERROR_ACCESS_DENIED == ::GetLastError()) {
187 return SBOX_TEST_DENIED;
188 } else {
189 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
192 return SBOX_TEST_SUCCEEDED;
195 // Move a file using the MoveFileEx api and returns if the call succeeded or
196 // not.
197 SBOX_TESTS_COMMAND int File_Rename(int argc, wchar_t **argv) {
198 if (argc != 2)
199 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
201 if (::MoveFileEx(argv[0], argv[1], 0))
202 return SBOX_TEST_SUCCEEDED;
204 if (::GetLastError() != ERROR_ACCESS_DENIED)
205 return SBOX_TEST_FAILED;
207 return SBOX_TEST_DENIED;
210 // Query the attributes of file in parameter using the NtQueryAttributesFile api
211 // and NtQueryFullAttributesFile and returns if the call succeeded or not. The
212 // second argument in argv is "d" or "f" telling if we expect the attributes to
213 // specify a file or a directory. The expected attribute has to match the real
214 // attributes for the call to be successful.
215 SBOX_TESTS_COMMAND int File_QueryAttributes(int argc, wchar_t **argv) {
216 BINDNTDLL(NtQueryAttributesFile);
217 BINDNTDLL(NtQueryFullAttributesFile);
218 BINDNTDLL(RtlInitUnicodeString);
219 if (!NtQueryAttributesFile || !NtQueryFullAttributesFile ||
220 !RtlInitUnicodeString)
221 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
223 if (argc != 2)
224 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
226 bool expect_directory = (L'd' == argv[1][0]);
228 UNICODE_STRING object_name;
229 base::string16 file = MakePathToSys(argv[0], true);
230 RtlInitUnicodeString(&object_name, file.c_str());
232 OBJECT_ATTRIBUTES obj_attributes = {0};
233 InitializeObjectAttributes(&obj_attributes, &object_name,
234 OBJ_CASE_INSENSITIVE, NULL, NULL);
236 FILE_BASIC_INFORMATION info = {0};
237 FILE_NETWORK_OPEN_INFORMATION full_info = {0};
238 NTSTATUS status1 = NtQueryAttributesFile(&obj_attributes, &info);
239 NTSTATUS status2 = NtQueryFullAttributesFile(&obj_attributes, &full_info);
241 if (status1 != status2)
242 return SBOX_TEST_FAILED;
244 if (NT_SUCCESS(status1)) {
245 if (info.FileAttributes != full_info.FileAttributes)
246 return SBOX_TEST_FAILED;
248 bool is_directory1 = (info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
249 if (expect_directory == is_directory1)
250 return SBOX_TEST_SUCCEEDED;
251 } else if (STATUS_ACCESS_DENIED == status1) {
252 return SBOX_TEST_DENIED;
253 } else if (STATUS_OBJECT_NAME_NOT_FOUND == status1) {
254 return SBOX_TEST_NOT_FOUND;
257 return SBOX_TEST_FAILED;
260 TEST(FilePolicyTest, DenyNtCreateCalc) {
261 TestRunner runner;
262 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY,
263 L"calc.exe"));
265 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 calc.exe"));
267 runner.SetTestState(BEFORE_REVERT);
268 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
271 TEST(FilePolicyTest, AllowNtCreateCalc) {
272 TestRunner runner;
273 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.exe"));
275 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
277 runner.SetTestState(BEFORE_REVERT);
278 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
281 TEST(FilePolicyTest, AllowNtCreateWithNativePath) {
282 base::string16 calc = MakePathToSys(L"calc.exe", false);
283 base::string16 nt_path;
284 ASSERT_TRUE(GetNtPathFromWin32Path(calc, &nt_path));
285 TestRunner runner;
286 runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, nt_path.c_str());
288 wchar_t buff[MAX_PATH];
289 ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
290 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
292 std::transform(nt_path.begin(), nt_path.end(), nt_path.begin(), std::tolower);
293 ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
294 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
297 TEST(FilePolicyTest, AllowReadOnly) {
298 TestRunner runner;
300 // Create a temp file because we need write access to it.
301 wchar_t temp_directory[MAX_PATH];
302 wchar_t temp_file_name[MAX_PATH];
303 ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
304 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
306 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
307 temp_file_name));
309 wchar_t command_read[MAX_PATH + 20] = {0};
310 wsprintf(command_read, L"File_Create Read \"%ls\"", temp_file_name);
311 wchar_t command_read_create[MAX_PATH + 20] = {0};
312 wsprintf(command_read_create, L"File_Create ReadCreate \"%ls\"",
313 temp_file_name);
314 wchar_t command_write[MAX_PATH + 20] = {0};
315 wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name);
317 // Verify that we cannot create the file after revert.
318 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_read_create));
320 // Verify that we don't have write access after revert.
321 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write));
323 // Verify that we have read access after revert.
324 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_read));
326 // Verify that we really have write access to the file.
327 runner.SetTestState(BEFORE_REVERT);
328 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write));
330 DeleteFile(temp_file_name);
333 TEST(FilePolicyTest, AllowWildcard) {
334 TestRunner runner;
336 // Create a temp file because we need write access to it.
337 wchar_t temp_directory[MAX_PATH];
338 wchar_t temp_file_name[MAX_PATH];
339 ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
340 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
342 wcscat_s(temp_directory, MAX_PATH, L"*");
343 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_directory));
345 wchar_t command_write[MAX_PATH + 20] = {0};
346 wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name);
348 // Verify that we have write access after revert.
349 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write));
351 DeleteFile(temp_file_name);
354 TEST(FilePolicyTest, AllowNtCreatePatternRule) {
355 TestRunner runner;
356 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"App*.dll"));
358 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
359 runner.RunTest(L"File_OpenSys32 appmgmts.dll"));
360 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
362 runner.SetTestState(BEFORE_REVERT);
363 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
364 runner.RunTest(L"File_OpenSys32 appmgmts.dll"));
365 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
368 TEST(FilePolicyTest, CheckNotFound) {
369 TestRunner runner;
370 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"n*.dll"));
372 EXPECT_EQ(SBOX_TEST_NOT_FOUND,
373 runner.RunTest(L"File_OpenSys32 notfound.dll"));
376 TEST(FilePolicyTest, CheckNoLeak) {
377 TestRunner runner;
378 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 notfound.exe"));
381 TEST(FilePolicyTest, TestQueryAttributesFile) {
382 TestRunner runner;
383 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY,
384 L"appmgmts.dll"));
385 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY,
386 L"notfound.exe"));
387 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"drivers"));
388 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_QUERY,
389 L"ipconfig.exe"));
391 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
392 runner.RunTest(L"File_QueryAttributes drivers d"));
394 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
395 runner.RunTest(L"File_QueryAttributes appmgmts.dll f"));
397 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
398 runner.RunTest(L"File_QueryAttributes ipconfig.exe f"));
400 EXPECT_EQ(SBOX_TEST_DENIED,
401 runner.RunTest(L"File_QueryAttributes ftp.exe f"));
403 EXPECT_EQ(SBOX_TEST_NOT_FOUND,
404 runner.RunTest(L"File_QueryAttributes notfound.exe f"));
407 // Makes sure that we don't leak information when there is not policy to allow
408 // a path.
409 TEST(FilePolicyTest, TestQueryAttributesFileNoPolicy) {
410 TestRunner runner;
411 EXPECT_EQ(SBOX_TEST_DENIED,
412 runner.RunTest(L"File_QueryAttributes ftp.exe f"));
414 EXPECT_EQ(SBOX_TEST_DENIED,
415 runner.RunTest(L"File_QueryAttributes notfound.exe f"));
418 TEST(FilePolicyTest, TestRename) {
419 TestRunner runner;
421 // Give access to the temp directory.
422 wchar_t temp_directory[MAX_PATH];
423 wchar_t temp_file_name1[MAX_PATH];
424 wchar_t temp_file_name2[MAX_PATH];
425 wchar_t temp_file_name3[MAX_PATH];
426 wchar_t temp_file_name4[MAX_PATH];
427 wchar_t temp_file_name5[MAX_PATH];
428 wchar_t temp_file_name6[MAX_PATH];
429 wchar_t temp_file_name7[MAX_PATH];
430 wchar_t temp_file_name8[MAX_PATH];
431 ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
432 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name1), 0u);
433 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name2), 0u);
434 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name3), 0u);
435 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name4), 0u);
436 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name5), 0u);
437 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name6), 0u);
438 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name7), 0u);
439 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name8), 0u);
442 // Add rules to make file1->file2 succeed.
443 ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name1));
444 ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name2));
446 // Add rules to make file3->file4 fail.
447 ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name3));
448 ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
449 temp_file_name4));
451 // Add rules to make file5->file6 fail.
452 ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
453 temp_file_name5));
454 ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name6));
456 // Add rules to make file7->no_pol_file fail.
457 ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name7));
459 // Delete the files where the files are going to be renamed to.
460 ::DeleteFile(temp_file_name2);
461 ::DeleteFile(temp_file_name4);
462 ::DeleteFile(temp_file_name6);
463 ::DeleteFile(temp_file_name8);
466 wchar_t command[MAX_PATH*2 + 20] = {0};
467 wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name1,
468 temp_file_name2);
469 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command));
471 wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name3,
472 temp_file_name4);
473 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
475 wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name5,
476 temp_file_name6);
477 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
479 wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name7,
480 temp_file_name8);
481 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
484 // Delete all the files in case they are still there.
485 ::DeleteFile(temp_file_name1);
486 ::DeleteFile(temp_file_name2);
487 ::DeleteFile(temp_file_name3);
488 ::DeleteFile(temp_file_name4);
489 ::DeleteFile(temp_file_name5);
490 ::DeleteFile(temp_file_name6);
491 ::DeleteFile(temp_file_name7);
492 ::DeleteFile(temp_file_name8);
495 TEST(FilePolicyTest, OpenSys32FilesDenyBecauseOfDir) {
496 TestRunner runner;
497 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY,
498 L"notepad.exe"));
500 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe"));
502 runner.SetTestState(BEFORE_REVERT);
503 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
504 runner.RunTest(L"File_Win32Create notepad.exe"));
507 TEST(FilePolicyTest, OpenSys32FilesAllowNotepad) {
508 TestRunner runner;
509 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY,
510 L"notepad.exe"));
512 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
513 runner.RunTest(L"File_Win32Create notepad.exe"));
515 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create calc.exe"));
517 runner.SetTestState(BEFORE_REVERT);
518 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
519 runner.RunTest(L"File_Win32Create notepad.exe"));
520 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_Win32Create calc.exe"));
523 TEST(FilePolicyTest, FileGetDiskSpace) {
524 TestRunner runner;
525 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_GetDiskSpace"));
526 runner.SetTestState(BEFORE_REVERT);
527 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
529 // Add an 'allow' rule in the windows\system32 such that GetDiskFreeSpaceEx
530 // succeeds (it does an NtOpenFile) but windows\system32\notepad.exe is
531 // denied since there is no wild card in the rule.
532 EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, L""));
533 runner.SetTestState(BEFORE_REVERT);
534 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
536 runner.SetTestState(AFTER_REVERT);
537 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
538 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe"));
541 TEST(FilePolicyTest, TestReparsePoint) {
542 TestRunner runner;
544 // Create a temp file because we need write access to it.
545 wchar_t temp_directory[MAX_PATH];
546 wchar_t temp_file_name[MAX_PATH];
547 ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
548 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
550 // Delete the file and create a directory instead.
551 ASSERT_TRUE(::DeleteFile(temp_file_name));
552 ASSERT_TRUE(::CreateDirectory(temp_file_name, NULL));
554 // Create a temporary file in the subfolder.
555 base::string16 subfolder = temp_file_name;
556 base::string16 temp_file_title = subfolder.substr(subfolder.rfind(L"\\") + 1);
557 base::string16 temp_file = subfolder + L"\\file_" + temp_file_title;
559 HANDLE file = ::CreateFile(temp_file.c_str(), FILE_ALL_ACCESS,
560 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
561 CREATE_ALWAYS, 0, NULL);
562 ASSERT_TRUE(INVALID_HANDLE_VALUE != file);
563 ASSERT_TRUE(::CloseHandle(file));
565 // Create a temporary file in the temp directory.
566 base::string16 temp_dir = temp_directory;
567 base::string16 temp_file_in_temp = temp_dir + L"file_" + temp_file_title;
568 file = ::CreateFile(temp_file_in_temp.c_str(), FILE_ALL_ACCESS,
569 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
570 CREATE_ALWAYS, 0, NULL);
571 ASSERT_TRUE(file != NULL);
572 ASSERT_TRUE(::CloseHandle(file));
574 // Give write access to the temp directory.
575 base::string16 temp_dir_wildcard = temp_dir + L"*";
576 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY,
577 temp_dir_wildcard.c_str()));
579 // Prepare the command to execute.
580 base::string16 command_write;
581 command_write += L"File_Create Write \"";
582 command_write += temp_file;
583 command_write += L"\"";
585 // Verify that we have write access to the original file
586 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write.c_str()));
588 // Replace the subfolder by a reparse point to %temp%.
589 ::DeleteFile(temp_file.c_str());
590 HANDLE dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS,
591 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
592 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
593 EXPECT_TRUE(INVALID_HANDLE_VALUE != dir);
595 base::string16 temp_dir_nt;
596 temp_dir_nt += L"\\??\\";
597 temp_dir_nt += temp_dir;
598 EXPECT_TRUE(SetReparsePoint(dir, temp_dir_nt.c_str()));
599 EXPECT_TRUE(::CloseHandle(dir));
601 // Try to open the file again.
602 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write.c_str()));
604 // Remove the reparse point.
605 dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS,
606 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
607 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
608 NULL);
609 EXPECT_TRUE(INVALID_HANDLE_VALUE != dir);
610 EXPECT_TRUE(DeleteReparsePoint(dir));
611 EXPECT_TRUE(::CloseHandle(dir));
613 // Cleanup.
614 EXPECT_TRUE(::DeleteFile(temp_file_in_temp.c_str()));
615 EXPECT_TRUE(::RemoveDirectory(subfolder.c_str()));
618 TEST(FilePolicyTest, CheckExistingNTPrefixEscape) {
619 base::string16 name = L"\\??\\NAME";
621 base::string16 result = FixNTPrefixForMatch(name);
623 EXPECT_STREQ(result.c_str(), L"\\/?/?\\NAME");
626 TEST(FilePolicyTest, CheckEscapedNTPrefixNoEscape) {
627 base::string16 name = L"\\/?/?\\NAME";
629 base::string16 result = FixNTPrefixForMatch(name);
631 EXPECT_STREQ(result.c_str(), name.c_str());
634 TEST(FilePolicyTest, CheckMissingNTPrefixEscape) {
635 base::string16 name = L"C:\\NAME";
637 base::string16 result = FixNTPrefixForMatch(name);
639 EXPECT_STREQ(result.c_str(), L"\\/?/?\\C:\\NAME");
642 } // namespace sandbox