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, 18 const wchar_t* job_name, 19 DWORD ui_exceptions, 20 size_t memory_limit) { 21 if (job_handle_) 22 return ERROR_ALREADY_INITIALIZED; 23 24 job_handle_ = ::CreateJobObject(NULL, // No security attribute 25 job_name); 26 if (!job_handle_) 27 return ::GetLastError(); 28 29 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0}; 30 JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; 31 32 // Set the settings for the different security levels. Note: The higher levels 33 // inherit from the lower levels. 34 switch (security_level) { 35 case JOB_LOCKDOWN: { 36 jeli.BasicLimitInformation.LimitFlags |= 37 JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION; 38 } 39 case JOB_RESTRICTED: { 40 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD; 41 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_READCLIPBOARD; 42 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES; 43 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_GLOBALATOMS; 44 } 45 case JOB_LIMITED_USER: { 46 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS; 47 jeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS; 48 jeli.BasicLimitInformation.ActiveProcessLimit = 1; 49 } 50 case JOB_INTERACTIVE: { 51 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS; 52 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DESKTOP; 53 jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS; 54 } 55 case JOB_UNPROTECTED: { 56 if (memory_limit) { 57 jeli.BasicLimitInformation.LimitFlags |= 58 JOB_OBJECT_LIMIT_PROCESS_MEMORY; 59 jeli.ProcessMemoryLimit = memory_limit; 60 } 61 62 jeli.BasicLimitInformation.LimitFlags |= 63 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; 64 break; 65 } 66 default: { 67 return ERROR_BAD_ARGUMENTS; 68 } 69 } 70 71 if (FALSE == ::SetInformationJobObject(job_handle_, 72 JobObjectExtendedLimitInformation, 73 &jeli, 74 sizeof(jeli))) { 75 return ::GetLastError(); 76 } 77 78 jbur.UIRestrictionsClass = jbur.UIRestrictionsClass & (~ui_exceptions); 79 if (FALSE == ::SetInformationJobObject(job_handle_, 80 JobObjectBasicUIRestrictions, 81 &jbur, 82 sizeof(jbur))) { 83 return ::GetLastError(); 84 } 85 86 return ERROR_SUCCESS; 87 } 88 89 DWORD Job::UserHandleGrantAccess(HANDLE handle) { 90 if (!job_handle_) 91 return ERROR_NO_DATA; 92 93 if (!::UserHandleGrantAccess(handle, 94 job_handle_, 95 TRUE)) { // Access allowed. 96 return ::GetLastError(); 97 } 98 99 return ERROR_SUCCESS; 100 } 101 102 HANDLE Job::Detach() { 103 HANDLE handle_temp = job_handle_; 104 job_handle_ = NULL; 105 return handle_temp; 106 } 107 108 DWORD Job::AssignProcessToJob(HANDLE process_handle) { 109 if (!job_handle_) 110 return ERROR_NO_DATA; 111 112 if (FALSE == ::AssignProcessToJobObject(job_handle_, process_handle)) 113 return ::GetLastError(); 114 115 return ERROR_SUCCESS; 116 } 117 118 } // namespace sandbox 119