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.
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))
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. 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
) {
35 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
37 bool read
= (_wcsicmp(argv
[0], L
"Read") == 0);
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
.Get() && file2
.Get())
46 return SBOX_TEST_SUCCEEDED
;
47 return SBOX_TEST_DENIED
;
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
,
55 if (file1
.Get() && file2
.Get())
56 return SBOX_TEST_SUCCEEDED
;
57 return SBOX_TEST_DENIED
;
61 SBOX_TESTS_COMMAND
int File_Win32Create(int argc
, wchar_t **argv
) {
63 SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
66 base::string16 full_path
= MakePathToSys(argv
[0], false);
67 if (full_path
.empty()) {
68 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
71 HANDLE file
= ::CreateFileW(full_path
.c_str(), GENERIC_READ
, kSharing
,
72 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
74 if (INVALID_HANDLE_VALUE
!= file
) {
76 return SBOX_TEST_SUCCEEDED
;
78 if (ERROR_ACCESS_DENIED
== ::GetLastError()) {
79 return SBOX_TEST_DENIED
;
81 return SBOX_TEST_FAILED
;
84 return SBOX_TEST_SUCCEEDED
;
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
;
96 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
98 base::string16
file(argv
[0]);
99 if (0 != _wcsnicmp(file
.c_str(), kNTObjManPrefix
, kNTObjManPrefixLen
))
100 file
= MakePathToSys(argv
[0], true);
102 UNICODE_STRING object_name
;
103 RtlInitUnicodeString(&object_name
, file
.c_str());
105 OBJECT_ATTRIBUTES obj_attributes
= {0};
106 InitializeObjectAttributes(&obj_attributes
, &object_name
,
107 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
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
,
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
;
122 return SBOX_TEST_FAILED
;
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
;
134 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
136 base::string16 file
= MakePathToSys(argv
[0], true);
137 UNICODE_STRING object_name
;
138 RtlInitUnicodeString(&object_name
, file
.c_str());
140 OBJECT_ATTRIBUTES obj_attributes
= {0};
141 InitializeObjectAttributes(&obj_attributes
, &object_name
,
142 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
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
;
156 return SBOX_TEST_FAILED
;
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
;
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
,
169 if ((total
.QuadPart
!= 0) && (free_total
.QuadPart
!=0)) {
170 return SBOX_TEST_SUCCEEDED
;
173 if (ERROR_ACCESS_DENIED
== ::GetLastError()) {
174 return SBOX_TEST_DENIED
;
176 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
179 return SBOX_TEST_SUCCEEDED
;
182 // Move a file using the MoveFileEx api and returns if the call succeeded or
184 SBOX_TESTS_COMMAND
int File_Rename(int argc
, wchar_t **argv
) {
186 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
188 if (::MoveFileEx(argv
[0], argv
[1], 0))
189 return SBOX_TEST_SUCCEEDED
;
191 if (::GetLastError() != ERROR_ACCESS_DENIED
)
192 return SBOX_TEST_FAILED
;
194 return SBOX_TEST_DENIED
;
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
;
211 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
213 bool expect_directory
= (L
'd' == argv
[1][0]);
215 UNICODE_STRING object_name
;
216 base::string16 file
= MakePathToSys(argv
[0], true);
217 RtlInitUnicodeString(&object_name
, file
.c_str());
219 OBJECT_ATTRIBUTES obj_attributes
= {0};
220 InitializeObjectAttributes(&obj_attributes
, &object_name
,
221 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
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
);
228 if (status1
!= status2
)
229 return SBOX_TEST_FAILED
;
231 if (NT_SUCCESS(status1
)) {
232 if (info
.FileAttributes
!= full_info
.FileAttributes
)
233 return SBOX_TEST_FAILED
;
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
;
244 return SBOX_TEST_FAILED
;
247 TEST(FilePolicyTest
, DenyNtCreateCalc
) {
249 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY
,
252 EXPECT_EQ(SBOX_TEST_DENIED
, runner
.RunTest(L
"File_CreateSys32 calc.exe"));
254 runner
.SetTestState(BEFORE_REVERT
);
255 EXPECT_EQ(SBOX_TEST_SUCCEEDED
, runner
.RunTest(L
"File_CreateSys32 calc.exe"));
258 TEST(FilePolicyTest
, AllowNtCreateCalc
) {
260 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY
, L
"calc.exe"));
262 EXPECT_EQ(SBOX_TEST_SUCCEEDED
, runner
.RunTest(L
"File_CreateSys32 calc.exe"));
264 runner
.SetTestState(BEFORE_REVERT
);
265 EXPECT_EQ(SBOX_TEST_SUCCEEDED
, runner
.RunTest(L
"File_CreateSys32 calc.exe"));
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
));
273 runner
.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY
, nt_path
.c_str());
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
));
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
));
284 TEST(FilePolicyTest
, AllowReadOnly
) {
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);
293 EXPECT_TRUE(runner
.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY
,
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
);
301 // Verify that we have read access after revert.
302 EXPECT_EQ(SBOX_TEST_SUCCEEDED
, runner
.RunTest(command_read
));
304 // Verify that we don't have write access after revert.
305 EXPECT_EQ(SBOX_TEST_DENIED
, runner
.RunTest(command_write
));
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
));
311 DeleteFile(temp_file_name
);
314 TEST(FilePolicyTest
, AllowWildcard
) {
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);
323 wcscat_s(temp_directory
, MAX_PATH
, L
"*");
324 EXPECT_TRUE(runner
.AddFsRule(TargetPolicy::FILES_ALLOW_ANY
, temp_directory
));
326 wchar_t command_write
[MAX_PATH
+ 20] = {0};
327 wsprintf(command_write
, L
"File_Create Write \"%ls\"", temp_file_name
);
329 // Verify that we have write access after revert.
330 EXPECT_EQ(SBOX_TEST_SUCCEEDED
, runner
.RunTest(command_write
));
332 DeleteFile(temp_file_name
);
335 TEST(FilePolicyTest
, AllowNtCreatePatternRule
) {
337 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY
, L
"App*.dll"));
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"));
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"));
349 TEST(FilePolicyTest
, CheckNotFound
) {
351 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY
, L
"n*.dll"));
353 EXPECT_EQ(SBOX_TEST_NOT_FOUND
,
354 runner
.RunTest(L
"File_OpenSys32 notfound.dll"));
357 TEST(FilePolicyTest
, CheckNoLeak
) {
359 EXPECT_EQ(SBOX_TEST_DENIED
, runner
.RunTest(L
"File_CreateSys32 notfound.exe"));
362 TEST(FilePolicyTest
, TestQueryAttributesFile
) {
364 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY
,
366 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY
,
368 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY
, L
"drivers"));
369 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_QUERY
,
372 EXPECT_EQ(SBOX_TEST_SUCCEEDED
,
373 runner
.RunTest(L
"File_QueryAttributes drivers d"));
375 EXPECT_EQ(SBOX_TEST_SUCCEEDED
,
376 runner
.RunTest(L
"File_QueryAttributes appmgmts.dll f"));
378 EXPECT_EQ(SBOX_TEST_SUCCEEDED
,
379 runner
.RunTest(L
"File_QueryAttributes ipconfig.exe f"));
381 EXPECT_EQ(SBOX_TEST_DENIED
,
382 runner
.RunTest(L
"File_QueryAttributes ftp.exe f"));
384 EXPECT_EQ(SBOX_TEST_NOT_FOUND
,
385 runner
.RunTest(L
"File_QueryAttributes notfound.exe f"));
388 // Makes sure that we don't leak information when there is not policy to allow
390 TEST(FilePolicyTest
, TestQueryAttributesFileNoPolicy
) {
392 EXPECT_EQ(SBOX_TEST_DENIED
,
393 runner
.RunTest(L
"File_QueryAttributes ftp.exe f"));
395 EXPECT_EQ(SBOX_TEST_DENIED
,
396 runner
.RunTest(L
"File_QueryAttributes notfound.exe f"));
399 TEST(FilePolicyTest
, TestRename
) {
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);
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
));
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
,
432 // Add rules to make file5->file6 fail.
433 ASSERT_TRUE(runner
.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY
,
435 ASSERT_TRUE(runner
.AddFsRule(TargetPolicy::FILES_ALLOW_ANY
, temp_file_name6
));
437 // Add rules to make file7->no_pol_file fail.
438 ASSERT_TRUE(runner
.AddFsRule(TargetPolicy::FILES_ALLOW_ANY
, temp_file_name7
));
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
);
447 wchar_t command
[MAX_PATH
*2 + 20] = {0};
448 wsprintf(command
, L
"File_Rename \"%ls\" \"%ls\"", temp_file_name1
,
450 EXPECT_EQ(SBOX_TEST_SUCCEEDED
, runner
.RunTest(command
));
452 wsprintf(command
, L
"File_Rename \"%ls\" \"%ls\"", temp_file_name3
,
454 EXPECT_EQ(SBOX_TEST_DENIED
, runner
.RunTest(command
));
456 wsprintf(command
, L
"File_Rename \"%ls\" \"%ls\"", temp_file_name5
,
458 EXPECT_EQ(SBOX_TEST_DENIED
, runner
.RunTest(command
));
460 wsprintf(command
, L
"File_Rename \"%ls\" \"%ls\"", temp_file_name7
,
462 EXPECT_EQ(SBOX_TEST_DENIED
, runner
.RunTest(command
));
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
);
476 TEST(FilePolicyTest
, OpenSys32FilesDenyBecauseOfDir
) {
478 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY
,
481 EXPECT_EQ(SBOX_TEST_DENIED
, runner
.RunTest(L
"File_Win32Create notepad.exe"));
483 runner
.SetTestState(BEFORE_REVERT
);
484 EXPECT_EQ(SBOX_TEST_SUCCEEDED
,
485 runner
.RunTest(L
"File_Win32Create notepad.exe"));
488 TEST(FilePolicyTest
, OpenSys32FilesAllowNotepad
) {
490 EXPECT_TRUE(runner
.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY
,
493 EXPECT_EQ(SBOX_TEST_SUCCEEDED
,
494 runner
.RunTest(L
"File_Win32Create notepad.exe"));
496 EXPECT_EQ(SBOX_TEST_DENIED
, runner
.RunTest(L
"File_Win32Create calc.exe"));
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"));
504 TEST(FilePolicyTest
, FileGetDiskSpace
) {
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"));
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"));
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"));
522 // http://crbug.com/146944
523 TEST(FilePolicyTest
, DISABLED_TestReparsePoint
) {
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);
532 // Delete the file and create a directory instead.
533 ASSERT_TRUE(::DeleteFile(temp_file_name
));
534 ASSERT_TRUE(::CreateDirectory(temp_file_name
, NULL
));
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
;
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
));
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
));
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()));
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
"\"";
567 // Verify that we have write access to the original file
568 EXPECT_EQ(SBOX_TEST_SUCCEEDED
, runner
.RunTest(command_write
.c_str()));
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
);
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
));
583 // Try to open the file again.
584 EXPECT_EQ(SBOX_TEST_DENIED
, runner
.RunTest(command_write
.c_str()));
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
,
591 EXPECT_TRUE(INVALID_HANDLE_VALUE
!= dir
);
592 EXPECT_TRUE(DeleteReparsePoint(dir
));
593 EXPECT_TRUE(::CloseHandle(dir
));
596 EXPECT_TRUE(::DeleteFile(temp_file_in_temp
.c_str()));
597 EXPECT_TRUE(::RemoveDirectory(subfolder
.c_str()));
600 TEST(FilePolicyTest
, CheckExistingNTPrefixEscape
) {
601 base::string16 name
= L
"\\??\\NAME";
603 base::string16 result
= FixNTPrefixForMatch(name
);
605 EXPECT_STREQ(result
.c_str(), L
"\\/?/?\\NAME");
608 TEST(FilePolicyTest
, CheckEscapedNTPrefixNoEscape
) {
609 base::string16 name
= L
"\\/?/?\\NAME";
611 base::string16 result
= FixNTPrefixForMatch(name
);
613 EXPECT_STREQ(result
.c_str(), name
.c_str());
616 TEST(FilePolicyTest
, CheckMissingNTPrefixEscape
) {
617 base::string16 name
= L
"C:\\NAME";
619 base::string16 result
= FixNTPrefixForMatch(name
);
621 EXPECT_STREQ(result
.c_str(), L
"\\/?/?\\C:\\NAME");
624 } // namespace sandbox