1// Copyright (c) 2012 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// This file contains the validation tests for the sandbox.
6// It includes the tests that need to be performed inside the
7// sandbox.
8
9#include <shlwapi.h>
10
11#include "base/win/windows_version.h"
12#include "testing/gtest/include/gtest/gtest.h"
13#include "sandbox/win/tests/common/controller.h"
14
15#pragma comment(lib, "shlwapi.lib")
16
17namespace {
18
19void TestProcessAccess(sandbox::TestRunner* runner, DWORD target) {
20  const wchar_t *kCommandTemplate = L"OpenProcessCmd %d %d";
21  wchar_t command[1024] = {0};
22
23  // Test all the scary process permissions.
24  wsprintf(command, kCommandTemplate, target, PROCESS_CREATE_THREAD);
25  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
26  wsprintf(command, kCommandTemplate, target, PROCESS_DUP_HANDLE);
27  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
28  wsprintf(command, kCommandTemplate, target, PROCESS_SET_INFORMATION);
29  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
30  wsprintf(command, kCommandTemplate, target, PROCESS_VM_OPERATION);
31  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
32  wsprintf(command, kCommandTemplate, target, PROCESS_VM_READ);
33  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
34  wsprintf(command, kCommandTemplate, target, PROCESS_VM_WRITE);
35  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
36  wsprintf(command, kCommandTemplate, target, PROCESS_QUERY_INFORMATION);
37  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
38  wsprintf(command, kCommandTemplate, target, WRITE_DAC);
39  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
40  wsprintf(command, kCommandTemplate, target, WRITE_OWNER);
41  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
42  wsprintf(command, kCommandTemplate, target, READ_CONTROL);
43  EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
44}
45
46}  // namespace
47
48namespace sandbox {
49
50// Returns true if the volume that contains any_path supports ACL security. The
51// input path can contain unexpanded environment strings. Returns false on any
52// failure or if the file system does not support file security (such as FAT).
53bool VolumeSupportsACLs(const wchar_t* any_path) {
54  wchar_t expand[MAX_PATH +1];
55  DWORD len =::ExpandEnvironmentStringsW(any_path, expand, _countof(expand));
56  if (0 == len) return false;
57  if (len >  _countof(expand)) return false;
58  if (!::PathStripToRootW(expand)) return false;
59  DWORD fs_flags = 0;
60  if (!::GetVolumeInformationW(expand, NULL, 0, 0, NULL, &fs_flags, NULL, 0))
61    return false;
62  if (fs_flags & FILE_PERSISTENT_ACLS) return true;
63  return false;
64}
65
66// Tests if the suite is working properly.
67TEST(ValidationSuite, TestSuite) {
68  TestRunner runner;
69  ASSERT_EQ(SBOX_TEST_PING_OK, runner.RunTest(L"ping"));
70}
71
72// Tests if the file system is correctly protected by the sandbox.
73TEST(ValidationSuite, TestFileSystem) {
74  // Do not perform the test if the system is using FAT or any other
75  // file system that does not have file security.
76  ASSERT_TRUE(VolumeSupportsACLs(L"%SystemDrive%\\"));
77  ASSERT_TRUE(VolumeSupportsACLs(L"%SystemRoot%\\"));
78  ASSERT_TRUE(VolumeSupportsACLs(L"%ProgramFiles%\\"));
79  ASSERT_TRUE(VolumeSupportsACLs(L"%Temp%\\"));
80  ASSERT_TRUE(VolumeSupportsACLs(L"%AppData%\\"));
81
82  TestRunner runner;
83  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %SystemDrive%"));
84  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %SystemRoot%"));
85  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %ProgramFiles%"));
86  EXPECT_EQ(SBOX_TEST_DENIED,
87      runner.RunTest(L"OpenFileCmd %SystemRoot%\\System32"));
88  EXPECT_EQ(SBOX_TEST_DENIED,
89      runner.RunTest(L"OpenFileCmd %SystemRoot%\\explorer.exe"));
90  EXPECT_EQ(SBOX_TEST_DENIED,
91      runner.RunTest(L"OpenFileCmd %SystemRoot%\\Cursors\\arrow_i.cur"));
92  EXPECT_EQ(SBOX_TEST_DENIED,
93      runner.RunTest(L"OpenFileCmd %AllUsersProfile%"));
94  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %Temp%"));
95  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %AppData%"));
96}
97
98// Tests if the registry is correctly protected by the sandbox.
99TEST(ValidationSuite, TestRegistry) {
100  TestRunner runner;
101  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKLM"));
102  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKCU"));
103  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKU"));
104  EXPECT_EQ(SBOX_TEST_DENIED,
105      runner.RunTest(
106          L"OpenKey HKLM "
107          L"\"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon\""));
108}
109
110// Tests that the permissions on the Windowstation does not allow the sandbox
111// to get to the interactive desktop or to make the sbox desktop interactive.
112TEST(ValidationSuite, TestDesktop) {
113  TestRunner runner;
114  runner.GetPolicy()->SetAlternateDesktop(true);
115  runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
116  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenInteractiveDesktop NULL"));
117  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"SwitchToSboxDesktop NULL"));
118}
119
120// Tests that the permissions on the Windowstation does not allow the sandbox
121// to get to the interactive desktop or to make the sbox desktop interactive.
122TEST(ValidationSuite, TestAlternateDesktop) {
123  base::win::Version version = base::win::GetVersion();
124  if (version < base::win::VERSION_WIN7)
125    return;
126
127  TestRunner runner;
128  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"EnumAlternateWinsta NULL"));
129
130  wchar_t command[1024] = {0};
131  runner.SetTimeout(3600000);
132  runner.GetPolicy()->SetAlternateDesktop(true);
133  runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
134  base::string16 desktop_name = runner.GetPolicy()->GetAlternateDesktop();
135  desktop_name = desktop_name.substr(desktop_name.find('\\') + 1);
136  wsprintf(command, L"OpenAlternateDesktop %lS", desktop_name.c_str());
137  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
138}
139
140// Tests if the windows are correctly protected by the sandbox.
141TEST(ValidationSuite, TestWindows) {
142  TestRunner runner;
143  wchar_t command[1024] = {0};
144
145  wsprintf(command, L"ValidWindow %d", ::GetDesktopWindow());
146  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
147
148  wsprintf(command, L"ValidWindow %d", ::FindWindow(NULL, NULL));
149  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
150}
151
152// Tests that a locked-down process cannot open another locked-down process.
153TEST(ValidationSuite, TestProcessDenyLockdown) {
154  TestRunner runner;
155  TestRunner target;
156  wchar_t command[1024] = {0};
157
158  target.SetAsynchronous(true);
159
160  EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000"));
161
162  TestProcessAccess(&runner, target.process_id());
163}
164
165// Tests that a low-integrity process cannot open a locked-down process (due
166// to the integrity label changing after startup via SetDelayedIntegrityLevel).
167TEST(ValidationSuite, TestProcessDenyLowIntegrity) {
168  // This test applies only to Vista and above.
169  if (base::win::Version() < base::win::VERSION_VISTA)
170    return;
171
172  TestRunner runner;
173  TestRunner target;
174  wchar_t command[1024] = {0};
175
176  target.SetAsynchronous(true);
177  target.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
178
179  runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
180  runner.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
181                                    USER_INTERACTIVE);
182
183  EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000"));
184
185  TestProcessAccess(&runner, target.process_id());
186}
187
188// Tests that a locked-down process cannot open a low-integrity process.
189TEST(ValidationSuite, TestProcessDenyBelowLowIntegrity) {
190  //  This test applies only to Vista and above.
191  if (base::win::Version() < base::win::VERSION_VISTA)
192    return;
193
194  TestRunner runner;
195  TestRunner target;
196  wchar_t command[1024] = {0};
197
198  target.SetAsynchronous(true);
199  target.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
200  target.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
201                                    USER_INTERACTIVE);
202
203  runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_UNTRUSTED);
204  runner.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
205                                    USER_INTERACTIVE);
206
207  EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000"));
208
209  TestProcessAccess(&runner, target.process_id());
210}
211
212// Tests if the threads are correctly protected by the sandbox.
213TEST(ValidationSuite, TestThread) {
214  TestRunner runner;
215  wchar_t command[1024] = {0};
216
217  wsprintf(command, L"OpenThreadCmd %d", ::GetCurrentThreadId());
218  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
219}
220
221// Tests if an over-limit allocation will be denied.
222TEST(ValidationSuite, TestMemoryLimit) {
223  TestRunner runner;
224  wchar_t command[1024] = {0};
225  const int kAllocationSize = 256 * 1024 * 1024;
226
227  wsprintf(command, L"AllocateCmd %d", kAllocationSize);
228  runner.GetPolicy()->SetJobMemoryLimit(kAllocationSize);
229  EXPECT_EQ(SBOX_FATAL_MEMORY_EXCEEDED, runner.RunTest(command));
230}
231
232// Tests a large allocation will succeed absent limits.
233TEST(ValidationSuite, TestMemoryNoLimit) {
234  TestRunner runner;
235  wchar_t command[1024] = {0};
236  const int kAllocationSize = 256 * 1024 * 1024;
237
238  wsprintf(command, L"AllocateCmd %d", kAllocationSize);
239  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command));
240}
241
242}  // namespace sandbox
243