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 "sandbox/win/src/job.h" 6 7 #include "base/win/windows_version.h" 8 #include "sandbox/win/src/restricted_token.h" 9 10 namespace sandbox { 11 12 Job::~Job() { 13 if (job_handle_) 14 ::CloseHandle(job_handle_); 15 }; 16 17 DWORD Job::Init(JobLevel security_level, wchar_t *job_name, 18 DWORD ui_exceptions) { 19 if (job_handle_) 20 return ERROR_ALREADY_INITIALIZED; 21 22 job_handle_ = ::CreateJobObject(NULL, // No security attribute 23 job_name); 24 if (!job_handle_) 25 return ::GetLastError(); 26 27 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0}; 28 JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; 29 30 // Set the settings for the different security levels. Note: The higher levels 31 // inherit from the lower levels. 32 switch (security_level) { 33 case JOB_LOCKDOWN: { 34 jeli.BasicLimitInformation.LimitFlags |= 35 JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION; 36 } 37 case JOB_RESTRICTED: { 38 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD; 39 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_READCLIPBOARD; 40 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES; 41 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_GLOBALATOMS; 42 } 43 case JOB_LIMITED_USER: { 44 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS; 45 jeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS; 46 jeli.BasicLimitInformation.ActiveProcessLimit = 1; 47 } 48 case JOB_INTERACTIVE: { 49 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS; 50 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DESKTOP; 51 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS; 52 } 53 case JOB_UNPROTECTED: { 54 // The JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag is not supported on 55 // Windows 2000. We need a mechanism on Windows 2000 to ensure 56 // that processes in the job are terminated when the job is closed 57 if (base::win::GetVersion() == base::win::VERSION_PRE_XP) 58 break; 59 60 jeli.BasicLimitInformation.LimitFlags |= 61 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; 62 break; 63 } 64 default: { 65 return ERROR_BAD_ARGUMENTS; 66 } 67 } 68 69 if (FALSE == ::SetInformationJobObject(job_handle_, 70 JobObjectExtendedLimitInformation, 71 &jeli, 72 sizeof(jeli))) { 73 return ::GetLastError(); 74 } 75 76 jbur.UIRestrictionsClass = jbur.UIRestrictionsClass & (~ui_exceptions); 77 if (FALSE == ::SetInformationJobObject(job_handle_, 78 JobObjectBasicUIRestrictions, 79 &jbur, 80 sizeof(jbur))) { 81 return ::GetLastError(); 82 } 83 84 return ERROR_SUCCESS; 85 } 86 87 DWORD Job::UserHandleGrantAccess(HANDLE handle) { 88 if (!job_handle_) 89 return ERROR_NO_DATA; 90 91 if (!::UserHandleGrantAccess(handle, 92 job_handle_, 93 TRUE)) { // Access allowed. 94 return ::GetLastError(); 95 } 96 97 return ERROR_SUCCESS; 98 } 99 100 HANDLE Job::Detach() { 101 HANDLE handle_temp = job_handle_; 102 job_handle_ = NULL; 103 return handle_temp; 104 } 105 106 DWORD Job::AssignProcessToJob(HANDLE process_handle) { 107 if (!job_handle_) 108 return ERROR_NO_DATA; 109 110 if (FALSE == ::AssignProcessToJobObject(job_handle_, process_handle)) 111 return ::GetLastError(); 112 113 return ERROR_SUCCESS; 114 } 115 116 } // namespace sandbox 117