Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | // This file contains unit tests for the job object. |
michael@0 | 6 | |
michael@0 | 7 | #include "base/win/scoped_process_information.h" |
michael@0 | 8 | #include "sandbox/win/src/job.h" |
michael@0 | 9 | #include "testing/gtest/include/gtest/gtest.h" |
michael@0 | 10 | |
michael@0 | 11 | namespace sandbox { |
michael@0 | 12 | |
michael@0 | 13 | // Tests the creation and destruction of the job. |
michael@0 | 14 | TEST(JobTest, TestCreation) { |
michael@0 | 15 | // Scope the creation of Job. |
michael@0 | 16 | { |
michael@0 | 17 | // Create the job. |
michael@0 | 18 | Job job; |
michael@0 | 19 | ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0)); |
michael@0 | 20 | |
michael@0 | 21 | // check if the job exists. |
michael@0 | 22 | HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, |
michael@0 | 23 | L"my_test_job_name"); |
michael@0 | 24 | ASSERT_TRUE(job_handle != NULL); |
michael@0 | 25 | |
michael@0 | 26 | if (job_handle) |
michael@0 | 27 | CloseHandle(job_handle); |
michael@0 | 28 | } |
michael@0 | 29 | |
michael@0 | 30 | // Check if the job is destroyed when the object goes out of scope. |
michael@0 | 31 | HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name"); |
michael@0 | 32 | ASSERT_TRUE(job_handle == NULL); |
michael@0 | 33 | ASSERT_EQ(ERROR_FILE_NOT_FOUND, ::GetLastError()); |
michael@0 | 34 | } |
michael@0 | 35 | |
michael@0 | 36 | // Tests the method "Detach". |
michael@0 | 37 | TEST(JobTest, TestDetach) { |
michael@0 | 38 | HANDLE job_handle; |
michael@0 | 39 | // Scope the creation of Job. |
michael@0 | 40 | { |
michael@0 | 41 | // Create the job. |
michael@0 | 42 | Job job; |
michael@0 | 43 | ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0)); |
michael@0 | 44 | |
michael@0 | 45 | job_handle = job.Detach(); |
michael@0 | 46 | ASSERT_TRUE(job_handle != NULL); |
michael@0 | 47 | } |
michael@0 | 48 | |
michael@0 | 49 | // Check to be sure that the job is still alive even after the object is gone |
michael@0 | 50 | // out of scope. |
michael@0 | 51 | HANDLE job_handle_dup = ::OpenJobObjectW(GENERIC_ALL, FALSE, |
michael@0 | 52 | L"my_test_job_name"); |
michael@0 | 53 | ASSERT_TRUE(job_handle_dup != NULL); |
michael@0 | 54 | |
michael@0 | 55 | // Remove all references. |
michael@0 | 56 | if (job_handle_dup) |
michael@0 | 57 | ::CloseHandle(job_handle_dup); |
michael@0 | 58 | |
michael@0 | 59 | if (job_handle) |
michael@0 | 60 | ::CloseHandle(job_handle); |
michael@0 | 61 | |
michael@0 | 62 | // Check if the jbo is really dead. |
michael@0 | 63 | job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name"); |
michael@0 | 64 | ASSERT_TRUE(job_handle == NULL); |
michael@0 | 65 | ASSERT_EQ(ERROR_FILE_NOT_FOUND, ::GetLastError()); |
michael@0 | 66 | } |
michael@0 | 67 | |
michael@0 | 68 | // Tests the ui exceptions |
michael@0 | 69 | TEST(JobTest, TestExceptions) { |
michael@0 | 70 | HANDLE job_handle; |
michael@0 | 71 | // Scope the creation of Job. |
michael@0 | 72 | { |
michael@0 | 73 | // Create the job. |
michael@0 | 74 | Job job; |
michael@0 | 75 | ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", |
michael@0 | 76 | JOB_OBJECT_UILIMIT_READCLIPBOARD)); |
michael@0 | 77 | |
michael@0 | 78 | job_handle = job.Detach(); |
michael@0 | 79 | ASSERT_TRUE(job_handle != NULL); |
michael@0 | 80 | |
michael@0 | 81 | JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; |
michael@0 | 82 | DWORD size = sizeof(jbur); |
michael@0 | 83 | BOOL result = ::QueryInformationJobObject(job_handle, |
michael@0 | 84 | JobObjectBasicUIRestrictions, |
michael@0 | 85 | &jbur, size, &size); |
michael@0 | 86 | ASSERT_TRUE(result); |
michael@0 | 87 | |
michael@0 | 88 | ASSERT_EQ(jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD, 0); |
michael@0 | 89 | ::CloseHandle(job_handle); |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | // Scope the creation of Job. |
michael@0 | 93 | { |
michael@0 | 94 | // Create the job. |
michael@0 | 95 | Job job; |
michael@0 | 96 | ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0)); |
michael@0 | 97 | |
michael@0 | 98 | job_handle = job.Detach(); |
michael@0 | 99 | ASSERT_TRUE(job_handle != NULL); |
michael@0 | 100 | |
michael@0 | 101 | JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; |
michael@0 | 102 | DWORD size = sizeof(jbur); |
michael@0 | 103 | BOOL result = ::QueryInformationJobObject(job_handle, |
michael@0 | 104 | JobObjectBasicUIRestrictions, |
michael@0 | 105 | &jbur, size, &size); |
michael@0 | 106 | ASSERT_TRUE(result); |
michael@0 | 107 | |
michael@0 | 108 | ASSERT_EQ(jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD, |
michael@0 | 109 | JOB_OBJECT_UILIMIT_READCLIPBOARD); |
michael@0 | 110 | ::CloseHandle(job_handle); |
michael@0 | 111 | } |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | // Tests the error case when the job is initialized twice. |
michael@0 | 115 | TEST(JobTest, DoubleInit) { |
michael@0 | 116 | // Create the job. |
michael@0 | 117 | Job job; |
michael@0 | 118 | ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0)); |
michael@0 | 119 | ASSERT_EQ(ERROR_ALREADY_INITIALIZED, job.Init(JOB_LOCKDOWN, L"test", 0)); |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | // Tests the error case when we use a method and the object is not yet |
michael@0 | 123 | // initialized. |
michael@0 | 124 | TEST(JobTest, NoInit) { |
michael@0 | 125 | Job job; |
michael@0 | 126 | ASSERT_EQ(ERROR_NO_DATA, job.UserHandleGrantAccess(NULL)); |
michael@0 | 127 | ASSERT_EQ(ERROR_NO_DATA, job.AssignProcessToJob(NULL)); |
michael@0 | 128 | ASSERT_TRUE(job.Detach() == NULL); |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | // Tests the initialization of the job with different security level. |
michael@0 | 132 | TEST(JobTest, SecurityLevel) { |
michael@0 | 133 | Job job1; |
michael@0 | 134 | ASSERT_EQ(ERROR_SUCCESS, job1.Init(JOB_LOCKDOWN, L"job1", 0)); |
michael@0 | 135 | |
michael@0 | 136 | Job job2; |
michael@0 | 137 | ASSERT_EQ(ERROR_SUCCESS, job2.Init(JOB_RESTRICTED, L"job2", 0)); |
michael@0 | 138 | |
michael@0 | 139 | Job job3; |
michael@0 | 140 | ASSERT_EQ(ERROR_SUCCESS, job3.Init(JOB_LIMITED_USER, L"job3", 0)); |
michael@0 | 141 | |
michael@0 | 142 | Job job4; |
michael@0 | 143 | ASSERT_EQ(ERROR_SUCCESS, job4.Init(JOB_INTERACTIVE, L"job4", 0)); |
michael@0 | 144 | |
michael@0 | 145 | Job job5; |
michael@0 | 146 | ASSERT_EQ(ERROR_SUCCESS, job5.Init(JOB_UNPROTECTED, L"job5", 0)); |
michael@0 | 147 | |
michael@0 | 148 | // JOB_NONE means we run without a job object so Init should fail. |
michael@0 | 149 | Job job6; |
michael@0 | 150 | ASSERT_EQ(ERROR_BAD_ARGUMENTS, job6.Init(JOB_NONE, L"job6", 0)); |
michael@0 | 151 | |
michael@0 | 152 | Job job7; |
michael@0 | 153 | ASSERT_EQ(ERROR_BAD_ARGUMENTS, job7.Init( |
michael@0 | 154 | static_cast<JobLevel>(JOB_NONE+1), L"job7", 0)); |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | // Tests the method "AssignProcessToJob". |
michael@0 | 158 | TEST(JobTest, ProcessInJob) { |
michael@0 | 159 | // Create the job. |
michael@0 | 160 | Job job; |
michael@0 | 161 | ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_UNPROTECTED, L"job_test_process", 0)); |
michael@0 | 162 | |
michael@0 | 163 | BOOL result = FALSE; |
michael@0 | 164 | |
michael@0 | 165 | wchar_t notepad[] = L"notepad"; |
michael@0 | 166 | STARTUPINFO si = { sizeof(si) }; |
michael@0 | 167 | base::win::ScopedProcessInformation pi; |
michael@0 | 168 | result = ::CreateProcess(NULL, notepad, NULL, NULL, FALSE, 0, NULL, NULL, &si, |
michael@0 | 169 | pi.Receive()); |
michael@0 | 170 | ASSERT_TRUE(result); |
michael@0 | 171 | ASSERT_EQ(ERROR_SUCCESS, job.AssignProcessToJob(pi.process_handle())); |
michael@0 | 172 | |
michael@0 | 173 | // Get the job handle. |
michael@0 | 174 | HANDLE job_handle = job.Detach(); |
michael@0 | 175 | |
michael@0 | 176 | // Check if the process is in the job. |
michael@0 | 177 | JOBOBJECT_BASIC_PROCESS_ID_LIST jbpidl = {0}; |
michael@0 | 178 | DWORD size = sizeof(jbpidl); |
michael@0 | 179 | result = ::QueryInformationJobObject(job_handle, |
michael@0 | 180 | JobObjectBasicProcessIdList, |
michael@0 | 181 | &jbpidl, size, &size); |
michael@0 | 182 | EXPECT_TRUE(result); |
michael@0 | 183 | |
michael@0 | 184 | EXPECT_EQ(1, jbpidl.NumberOfAssignedProcesses); |
michael@0 | 185 | EXPECT_EQ(1, jbpidl.NumberOfProcessIdsInList); |
michael@0 | 186 | EXPECT_EQ(pi.process_id(), jbpidl.ProcessIdList[0]); |
michael@0 | 187 | |
michael@0 | 188 | EXPECT_TRUE(::TerminateProcess(pi.process_handle(), 0)); |
michael@0 | 189 | |
michael@0 | 190 | EXPECT_TRUE(::CloseHandle(job_handle)); |
michael@0 | 191 | } |
michael@0 | 192 | |
michael@0 | 193 | } // namespace sandbox |