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

Side by Side Diff: sandbox/win/src/policy_target_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/policy_target.cc ('k') | sandbox/win/src/process_mitigations.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) 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 #include "base/memory/shared_memory.h"
6 #include "base/strings/string_number_conversions.h"
7 #include "base/strings/string_piece.h"
8 #include "base/win/scoped_process_information.h"
9 #include "base/win/windows_version.h"
10 #include "sandbox/win/src/sandbox.h"
11 #include "sandbox/win/src/sandbox_factory.h"
12 #include "sandbox/win/src/sandbox_utils.h"
13 #include "sandbox/win/src/target_services.h"
14 #include "sandbox/win/tests/common/controller.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 #if defined(OS_WIN)
18 #include "base/win/win_util.h"
19 #endif
20
21 namespace sandbox {
22
23 #define BINDNTDLL(name) \
24 name ## Function name = reinterpret_cast<name ## Function>( \
25 ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name))
26
27 // Reverts to self and verify that SetInformationToken was faked. Returns
28 // SBOX_TEST_SUCCEEDED if faked and SBOX_TEST_FAILED if not faked.
29 SBOX_TESTS_COMMAND int PolicyTargetTest_token(int argc, wchar_t **argv) {
30 HANDLE thread_token;
31 // Get the thread token, using impersonation.
32 if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE |
33 TOKEN_DUPLICATE, FALSE, &thread_token))
34 return ::GetLastError();
35
36 ::RevertToSelf();
37 ::CloseHandle(thread_token);
38
39 int ret = SBOX_TEST_FAILED;
40 if (::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
41 FALSE, &thread_token)) {
42 ret = SBOX_TEST_SUCCEEDED;
43 ::CloseHandle(thread_token);
44 }
45 return ret;
46 }
47
48 // Stores the high privilege token on a static variable, change impersonation
49 // again to that one and verify that we are not interfering anymore with
50 // RevertToSelf.
51 SBOX_TESTS_COMMAND int PolicyTargetTest_steal(int argc, wchar_t **argv) {
52 static HANDLE thread_token;
53 if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) {
54 if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE |
55 TOKEN_DUPLICATE, FALSE, &thread_token))
56 return ::GetLastError();
57 } else {
58 if (!::SetThreadToken(NULL, thread_token))
59 return ::GetLastError();
60
61 // See if we fake the call again.
62 int ret = PolicyTargetTest_token(argc, argv);
63 ::CloseHandle(thread_token);
64 return ret;
65 }
66 return 0;
67 }
68
69 // Opens the thread token with and without impersonation.
70 SBOX_TESTS_COMMAND int PolicyTargetTest_token2(int argc, wchar_t **argv) {
71 HANDLE thread_token;
72 // Get the thread token, using impersonation.
73 if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE |
74 TOKEN_DUPLICATE, FALSE, &thread_token))
75 return ::GetLastError();
76 ::CloseHandle(thread_token);
77
78 // Get the thread token, without impersonation.
79 if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
80 TRUE, &thread_token))
81 return ::GetLastError();
82 ::CloseHandle(thread_token);
83 return SBOX_TEST_SUCCEEDED;
84 }
85
86 // Opens the thread token with and without impersonation, using
87 // NtOpenThreadTokenEX.
88 SBOX_TESTS_COMMAND int PolicyTargetTest_token3(int argc, wchar_t **argv) {
89 BINDNTDLL(NtOpenThreadTokenEx);
90 if (!NtOpenThreadTokenEx)
91 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
92
93 HANDLE thread_token;
94 // Get the thread token, using impersonation.
95 NTSTATUS status = NtOpenThreadTokenEx(GetCurrentThread(),
96 TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
97 FALSE, 0, &thread_token);
98 if (status == STATUS_NO_TOKEN)
99 return ERROR_NO_TOKEN;
100 if (!NT_SUCCESS(status))
101 return SBOX_TEST_FAILED;
102
103 ::CloseHandle(thread_token);
104
105 // Get the thread token, without impersonation.
106 status = NtOpenThreadTokenEx(GetCurrentThread(),
107 TOKEN_IMPERSONATE | TOKEN_DUPLICATE, TRUE, 0,
108 &thread_token);
109 if (!NT_SUCCESS(status))
110 return SBOX_TEST_FAILED;
111
112 ::CloseHandle(thread_token);
113 return SBOX_TEST_SUCCEEDED;
114 }
115
116 // Tests that we can open the current thread.
117 SBOX_TESTS_COMMAND int PolicyTargetTest_thread(int argc, wchar_t **argv) {
118 DWORD thread_id = ::GetCurrentThreadId();
119 HANDLE thread = ::OpenThread(SYNCHRONIZE, FALSE, thread_id);
120 if (!thread)
121 return ::GetLastError();
122 if (!::CloseHandle(thread))
123 return ::GetLastError();
124
125 return SBOX_TEST_SUCCEEDED;
126 }
127
128 // New thread entry point: do nothing.
129 DWORD WINAPI PolicyTargetTest_thread_main(void* param) {
130 ::Sleep(INFINITE);
131 return 0;
132 }
133
134 // Tests that we can create a new thread, and open it.
135 SBOX_TESTS_COMMAND int PolicyTargetTest_thread2(int argc, wchar_t **argv) {
136 // Use default values to create a new thread.
137 DWORD thread_id;
138 HANDLE thread = ::CreateThread(NULL, 0, &PolicyTargetTest_thread_main, 0, 0,
139 &thread_id);
140 if (!thread)
141 return ::GetLastError();
142 if (!::CloseHandle(thread))
143 return ::GetLastError();
144
145 thread = ::OpenThread(SYNCHRONIZE, FALSE, thread_id);
146 if (!thread)
147 return ::GetLastError();
148
149 if (!::CloseHandle(thread))
150 return ::GetLastError();
151
152 return SBOX_TEST_SUCCEEDED;
153 }
154
155 // Tests that we can call CreateProcess.
156 SBOX_TESTS_COMMAND int PolicyTargetTest_process(int argc, wchar_t **argv) {
157 // Use default values to create a new process.
158 STARTUPINFO startup_info = {0};
159 startup_info.cb = sizeof(startup_info);
160 PROCESS_INFORMATION temp_process_info = {};
161 // Note: CreateProcessW() can write to its lpCommandLine, don't pass a
162 // raw string literal.
163 base::string16 writable_cmdline_str(L"foo.exe");
164 if (!::CreateProcessW(L"foo.exe", &writable_cmdline_str[0], NULL, NULL, FALSE,
165 0, NULL, NULL, &startup_info, &temp_process_info))
166 return SBOX_TEST_SUCCEEDED;
167 base::win::ScopedProcessInformation process_info(temp_process_info);
168 return SBOX_TEST_FAILED;
169 }
170
171 TEST(PolicyTargetTest, SetInformationThread) {
172 TestRunner runner;
173 runner.SetTestState(BEFORE_REVERT);
174 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token"));
175
176 runner.SetTestState(AFTER_REVERT);
177 EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token"));
178
179 runner.SetTestState(EVERY_STATE);
180 EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"PolicyTargetTest_steal"));
181 }
182
183 TEST(PolicyTargetTest, OpenThreadToken) {
184 TestRunner runner;
185 runner.SetTestState(BEFORE_REVERT);
186 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token2"));
187
188 runner.SetTestState(AFTER_REVERT);
189 EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token2"));
190 }
191
192 TEST(PolicyTargetTest, OpenThreadTokenEx) {
193 TestRunner runner;
194
195 runner.SetTestState(BEFORE_REVERT);
196 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token3"));
197
198 runner.SetTestState(AFTER_REVERT);
199 EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token3"));
200 }
201
202 TEST(PolicyTargetTest, OpenThread) {
203 TestRunner runner;
204 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread")) <<
205 "Opens the current thread";
206
207 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread2")) <<
208 "Creates a new thread and opens it";
209 }
210
211 TEST(PolicyTargetTest, OpenProcess) {
212 TestRunner runner;
213 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_process")) <<
214 "Opens a process";
215 }
216
217 // Launches the app in the sandbox and ask it to wait in an
218 // infinite loop. Waits for 2 seconds and then check if the
219 // desktop associated with the app thread is not the same as the
220 // current desktop.
221 TEST(PolicyTargetTest, DesktopPolicy) {
222 BrokerServices* broker = GetBroker();
223
224 // Precreate the desktop.
225 TargetPolicy* temp_policy = broker->CreatePolicy();
226 temp_policy->CreateAlternateDesktop(false);
227 temp_policy->Release();
228
229 ASSERT_TRUE(broker != NULL);
230
231 // Get the path to the sandboxed app.
232 wchar_t prog_name[MAX_PATH];
233 GetModuleFileNameW(NULL, prog_name, MAX_PATH);
234
235 base::string16 arguments(L"\"");
236 arguments += prog_name;
237 arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
238
239 // Launch the app.
240 ResultCode result = SBOX_ALL_OK;
241 base::win::ScopedProcessInformation target;
242
243 TargetPolicy* policy = broker->CreatePolicy();
244 policy->SetAlternateDesktop(false);
245 policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
246 PROCESS_INFORMATION temp_process_info = {};
247 result = broker->SpawnTarget(prog_name, arguments.c_str(), policy,
248 &temp_process_info);
249 base::string16 desktop_name = policy->GetAlternateDesktop();
250 policy->Release();
251
252 EXPECT_EQ(SBOX_ALL_OK, result);
253 if (result == SBOX_ALL_OK)
254 target.Set(temp_process_info);
255
256 EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
257
258 EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
259 ::WaitForSingleObject(target.process_handle(), 2000));
260
261 EXPECT_NE(::GetThreadDesktop(target.thread_id()),
262 ::GetThreadDesktop(::GetCurrentThreadId()));
263
264 HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
265 EXPECT_TRUE(NULL != desk);
266 EXPECT_TRUE(::CloseDesktop(desk));
267 EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
268
269 ::WaitForSingleObject(target.process_handle(), INFINITE);
270
271 // Close the desktop handle.
272 temp_policy = broker->CreatePolicy();
273 temp_policy->DestroyAlternateDesktop();
274 temp_policy->Release();
275
276 // Make sure the desktop does not exist anymore.
277 desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
278 EXPECT_TRUE(NULL == desk);
279 }
280
281 // Launches the app in the sandbox and ask it to wait in an
282 // infinite loop. Waits for 2 seconds and then check if the
283 // winstation associated with the app thread is not the same as the
284 // current desktop.
285 TEST(PolicyTargetTest, WinstaPolicy) {
286 BrokerServices* broker = GetBroker();
287
288 // Precreate the desktop.
289 TargetPolicy* temp_policy = broker->CreatePolicy();
290 temp_policy->CreateAlternateDesktop(true);
291 temp_policy->Release();
292
293 ASSERT_TRUE(broker != NULL);
294
295 // Get the path to the sandboxed app.
296 wchar_t prog_name[MAX_PATH];
297 GetModuleFileNameW(NULL, prog_name, MAX_PATH);
298
299 base::string16 arguments(L"\"");
300 arguments += prog_name;
301 arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
302
303 // Launch the app.
304 ResultCode result = SBOX_ALL_OK;
305 base::win::ScopedProcessInformation target;
306
307 TargetPolicy* policy = broker->CreatePolicy();
308 policy->SetAlternateDesktop(true);
309 policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
310 PROCESS_INFORMATION temp_process_info = {};
311 result = broker->SpawnTarget(prog_name, arguments.c_str(), policy,
312 &temp_process_info);
313 base::string16 desktop_name = policy->GetAlternateDesktop();
314 policy->Release();
315
316 EXPECT_EQ(SBOX_ALL_OK, result);
317 if (result == SBOX_ALL_OK)
318 target.Set(temp_process_info);
319
320 EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
321
322 EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
323 ::WaitForSingleObject(target.process_handle(), 2000));
324
325 EXPECT_NE(::GetThreadDesktop(target.thread_id()),
326 ::GetThreadDesktop(::GetCurrentThreadId()));
327
328 ASSERT_FALSE(desktop_name.empty());
329
330 // Make sure there is a backslash, for the window station name.
331 EXPECT_NE(desktop_name.find_first_of(L'\\'), base::string16::npos);
332
333 // Isolate the desktop name.
334 desktop_name = desktop_name.substr(desktop_name.find_first_of(L'\\') + 1);
335
336 HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
337 // This should fail if the desktop is really on another window station.
338 EXPECT_FALSE(NULL != desk);
339 EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
340
341 ::WaitForSingleObject(target.process_handle(), INFINITE);
342
343 // Close the desktop handle.
344 temp_policy = broker->CreatePolicy();
345 temp_policy->DestroyAlternateDesktop();
346 temp_policy->Release();
347 }
348
349 // Launches the app in the sandbox and share a handle with it. The app should
350 // be able to use the handle.
351 TEST(PolicyTargetTest, ShareHandleTest) {
352
353 BrokerServices* broker = GetBroker();
354 ASSERT_TRUE(broker != NULL);
355
356 base::StringPiece contents = "Hello World";
357 std::string name = "TestSharedMemory";
358 base::SharedMemoryCreateOptions options;
359 options.size = contents.size();
360 options.share_read_only = true;
361 options.name_deprecated = &name;
362 base::SharedMemory writable_shmem;
363 ASSERT_TRUE(writable_shmem.Create(options));
364 ASSERT_TRUE(writable_shmem.Map(options.size));
365 memcpy(writable_shmem.memory(), contents.data(), contents.size());
366
367 base::SharedMemory read_only_view;
368 ASSERT_TRUE(read_only_view.Open(name, true));
369
370 // Get the path to the sandboxed app.
371 wchar_t prog_name[MAX_PATH];
372 GetModuleFileNameW(NULL, prog_name, MAX_PATH);
373
374 TargetPolicy* policy = broker->CreatePolicy();
375 policy->AddHandleToShare(read_only_view.handle().GetHandle());
376
377 base::string16 arguments(L"\"");
378 arguments += prog_name;
379 arguments += L"\" -child 0 shared_memory_handle ";
380 arguments += base::UintToString16(
381 base::win::HandleToUint32(read_only_view.handle().GetHandle()));
382
383 // Launch the app.
384 ResultCode result = SBOX_ALL_OK;
385 base::win::ScopedProcessInformation target;
386
387 policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
388 PROCESS_INFORMATION temp_process_info = {};
389 result = broker->SpawnTarget(prog_name, arguments.c_str(), policy,
390 &temp_process_info);
391 policy->Release();
392
393 EXPECT_EQ(SBOX_ALL_OK, result);
394 if (result == SBOX_ALL_OK)
395 target.Set(temp_process_info);
396
397 EXPECT_EQ(1u, ::ResumeThread(target.thread_handle()));
398
399 EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
400 ::WaitForSingleObject(target.process_handle(), 2000));
401
402 EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
403
404 ::WaitForSingleObject(target.process_handle(), INFINITE);
405 }
406
407 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/win/src/policy_target.cc ('k') | sandbox/win/src/process_mitigations.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698