security/sandbox/win/src/job_unittest.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/sandbox/win/src/job_unittest.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,193 @@
     1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +// This file contains unit tests for the job object.
     1.9 +
    1.10 +#include "base/win/scoped_process_information.h"
    1.11 +#include "sandbox/win/src/job.h"
    1.12 +#include "testing/gtest/include/gtest/gtest.h"
    1.13 +
    1.14 +namespace sandbox {
    1.15 +
    1.16 +// Tests the creation and destruction of the job.
    1.17 +TEST(JobTest, TestCreation) {
    1.18 +  // Scope the creation of Job.
    1.19 +  {
    1.20 +    // Create the job.
    1.21 +    Job job;
    1.22 +    ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0));
    1.23 +
    1.24 +    // check if the job exists.
    1.25 +    HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE,
    1.26 +                                         L"my_test_job_name");
    1.27 +    ASSERT_TRUE(job_handle != NULL);
    1.28 +
    1.29 +    if (job_handle)
    1.30 +      CloseHandle(job_handle);
    1.31 +  }
    1.32 +
    1.33 +  // Check if the job is destroyed when the object goes out of scope.
    1.34 +  HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name");
    1.35 +  ASSERT_TRUE(job_handle == NULL);
    1.36 +  ASSERT_EQ(ERROR_FILE_NOT_FOUND, ::GetLastError());
    1.37 +}
    1.38 +
    1.39 +// Tests the method "Detach".
    1.40 +TEST(JobTest, TestDetach) {
    1.41 +  HANDLE job_handle;
    1.42 +  // Scope the creation of Job.
    1.43 +  {
    1.44 +    // Create the job.
    1.45 +    Job job;
    1.46 +    ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0));
    1.47 +
    1.48 +    job_handle = job.Detach();
    1.49 +    ASSERT_TRUE(job_handle != NULL);
    1.50 +  }
    1.51 +
    1.52 +  // Check to be sure that the job is still alive even after the object is gone
    1.53 +  // out of scope.
    1.54 +  HANDLE job_handle_dup = ::OpenJobObjectW(GENERIC_ALL, FALSE,
    1.55 +                                           L"my_test_job_name");
    1.56 +  ASSERT_TRUE(job_handle_dup != NULL);
    1.57 +
    1.58 +  // Remove all references.
    1.59 +  if (job_handle_dup)
    1.60 +    ::CloseHandle(job_handle_dup);
    1.61 +
    1.62 +  if (job_handle)
    1.63 +    ::CloseHandle(job_handle);
    1.64 +
    1.65 +  // Check if the jbo is really dead.
    1.66 +  job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name");
    1.67 +  ASSERT_TRUE(job_handle == NULL);
    1.68 +  ASSERT_EQ(ERROR_FILE_NOT_FOUND, ::GetLastError());
    1.69 +}
    1.70 +
    1.71 +// Tests the ui exceptions
    1.72 +TEST(JobTest, TestExceptions) {
    1.73 +  HANDLE job_handle;
    1.74 +  // Scope the creation of Job.
    1.75 +  {
    1.76 +    // Create the job.
    1.77 +    Job job;
    1.78 +    ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name",
    1.79 +                                      JOB_OBJECT_UILIMIT_READCLIPBOARD));
    1.80 +
    1.81 +    job_handle = job.Detach();
    1.82 +    ASSERT_TRUE(job_handle != NULL);
    1.83 +
    1.84 +    JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0};
    1.85 +    DWORD size = sizeof(jbur);
    1.86 +    BOOL result = ::QueryInformationJobObject(job_handle,
    1.87 +                                              JobObjectBasicUIRestrictions,
    1.88 +                                              &jbur, size, &size);
    1.89 +    ASSERT_TRUE(result);
    1.90 +
    1.91 +    ASSERT_EQ(jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD, 0);
    1.92 +    ::CloseHandle(job_handle);
    1.93 +  }
    1.94 +
    1.95 +  // Scope the creation of Job.
    1.96 +  {
    1.97 +    // Create the job.
    1.98 +    Job job;
    1.99 +    ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0));
   1.100 +
   1.101 +    job_handle = job.Detach();
   1.102 +    ASSERT_TRUE(job_handle != NULL);
   1.103 +
   1.104 +    JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0};
   1.105 +    DWORD size = sizeof(jbur);
   1.106 +    BOOL result = ::QueryInformationJobObject(job_handle,
   1.107 +                                              JobObjectBasicUIRestrictions,
   1.108 +                                              &jbur, size, &size);
   1.109 +    ASSERT_TRUE(result);
   1.110 +
   1.111 +    ASSERT_EQ(jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD,
   1.112 +              JOB_OBJECT_UILIMIT_READCLIPBOARD);
   1.113 +    ::CloseHandle(job_handle);
   1.114 +  }
   1.115 +}
   1.116 +
   1.117 +// Tests the error case when the job is initialized twice.
   1.118 +TEST(JobTest, DoubleInit) {
   1.119 +  // Create the job.
   1.120 +  Job job;
   1.121 +  ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0));
   1.122 +  ASSERT_EQ(ERROR_ALREADY_INITIALIZED, job.Init(JOB_LOCKDOWN, L"test", 0));
   1.123 +}
   1.124 +
   1.125 +// Tests the error case when we use a method and the object is not yet
   1.126 +// initialized.
   1.127 +TEST(JobTest, NoInit) {
   1.128 +  Job job;
   1.129 +  ASSERT_EQ(ERROR_NO_DATA, job.UserHandleGrantAccess(NULL));
   1.130 +  ASSERT_EQ(ERROR_NO_DATA, job.AssignProcessToJob(NULL));
   1.131 +  ASSERT_TRUE(job.Detach() == NULL);
   1.132 +}
   1.133 +
   1.134 +// Tests the initialization of the job with different security level.
   1.135 +TEST(JobTest, SecurityLevel) {
   1.136 +  Job job1;
   1.137 +  ASSERT_EQ(ERROR_SUCCESS, job1.Init(JOB_LOCKDOWN, L"job1", 0));
   1.138 +
   1.139 +  Job job2;
   1.140 +  ASSERT_EQ(ERROR_SUCCESS, job2.Init(JOB_RESTRICTED, L"job2", 0));
   1.141 +
   1.142 +  Job job3;
   1.143 +  ASSERT_EQ(ERROR_SUCCESS, job3.Init(JOB_LIMITED_USER, L"job3", 0));
   1.144 +
   1.145 +  Job job4;
   1.146 +  ASSERT_EQ(ERROR_SUCCESS, job4.Init(JOB_INTERACTIVE, L"job4", 0));
   1.147 +
   1.148 +  Job job5;
   1.149 +  ASSERT_EQ(ERROR_SUCCESS, job5.Init(JOB_UNPROTECTED, L"job5", 0));
   1.150 +
   1.151 +  // JOB_NONE means we run without a job object so Init should fail.
   1.152 +  Job job6;
   1.153 +  ASSERT_EQ(ERROR_BAD_ARGUMENTS, job6.Init(JOB_NONE, L"job6", 0));
   1.154 +
   1.155 +  Job job7;
   1.156 +  ASSERT_EQ(ERROR_BAD_ARGUMENTS, job7.Init(
   1.157 +      static_cast<JobLevel>(JOB_NONE+1), L"job7", 0));
   1.158 +}
   1.159 +
   1.160 +// Tests the method "AssignProcessToJob".
   1.161 +TEST(JobTest, ProcessInJob) {
   1.162 +  // Create the job.
   1.163 +  Job job;
   1.164 +  ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_UNPROTECTED, L"job_test_process", 0));
   1.165 +
   1.166 +  BOOL result = FALSE;
   1.167 +
   1.168 +  wchar_t notepad[] = L"notepad";
   1.169 +  STARTUPINFO si = { sizeof(si) };
   1.170 +  base::win::ScopedProcessInformation pi;
   1.171 +  result = ::CreateProcess(NULL, notepad, NULL, NULL, FALSE, 0, NULL, NULL, &si,
   1.172 +                           pi.Receive());
   1.173 +  ASSERT_TRUE(result);
   1.174 +  ASSERT_EQ(ERROR_SUCCESS, job.AssignProcessToJob(pi.process_handle()));
   1.175 +
   1.176 +  // Get the job handle.
   1.177 +  HANDLE job_handle = job.Detach();
   1.178 +
   1.179 +  // Check if the process is in the job.
   1.180 +  JOBOBJECT_BASIC_PROCESS_ID_LIST jbpidl = {0};
   1.181 +  DWORD size = sizeof(jbpidl);
   1.182 +  result = ::QueryInformationJobObject(job_handle,
   1.183 +                                       JobObjectBasicProcessIdList,
   1.184 +                                       &jbpidl, size, &size);
   1.185 +  EXPECT_TRUE(result);
   1.186 +
   1.187 +  EXPECT_EQ(1, jbpidl.NumberOfAssignedProcesses);
   1.188 +  EXPECT_EQ(1, jbpidl.NumberOfProcessIdsInList);
   1.189 +  EXPECT_EQ(pi.process_id(), jbpidl.ProcessIdList[0]);
   1.190 +
   1.191 +  EXPECT_TRUE(::TerminateProcess(pi.process_handle(), 0));
   1.192 +
   1.193 +  EXPECT_TRUE(::CloseHandle(job_handle));
   1.194 +}
   1.195 +
   1.196 +}  // namespace sandbox

mercurial