Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: sandbox/win/src/file_policy_test.cc

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

Powered by Google App Engine
This is Rietveld 408576698