michael@0: // Copyright (c) 2011 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "sandbox/win/src/job.h" michael@0: michael@0: #include "base/win/windows_version.h" michael@0: #include "sandbox/win/src/restricted_token.h" michael@0: michael@0: namespace sandbox { michael@0: michael@0: Job::~Job() { michael@0: if (job_handle_) michael@0: ::CloseHandle(job_handle_); michael@0: }; michael@0: michael@0: DWORD Job::Init(JobLevel security_level, wchar_t *job_name, michael@0: DWORD ui_exceptions) { michael@0: if (job_handle_) michael@0: return ERROR_ALREADY_INITIALIZED; michael@0: michael@0: job_handle_ = ::CreateJobObject(NULL, // No security attribute michael@0: job_name); michael@0: if (!job_handle_) michael@0: return ::GetLastError(); michael@0: michael@0: JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0}; michael@0: JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; michael@0: michael@0: // Set the settings for the different security levels. Note: The higher levels michael@0: // inherit from the lower levels. michael@0: switch (security_level) { michael@0: case JOB_LOCKDOWN: { michael@0: jeli.BasicLimitInformation.LimitFlags |= michael@0: JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION; michael@0: } michael@0: case JOB_RESTRICTED: { michael@0: jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD; michael@0: jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_READCLIPBOARD; michael@0: jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES; michael@0: jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_GLOBALATOMS; michael@0: } michael@0: case JOB_LIMITED_USER: { michael@0: jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS; michael@0: jeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS; michael@0: jeli.BasicLimitInformation.ActiveProcessLimit = 1; michael@0: } michael@0: case JOB_INTERACTIVE: { michael@0: jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS; michael@0: jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DESKTOP; michael@0: jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS; michael@0: } michael@0: case JOB_UNPROTECTED: { michael@0: // The JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag is not supported on michael@0: // Windows 2000. We need a mechanism on Windows 2000 to ensure michael@0: // that processes in the job are terminated when the job is closed michael@0: if (base::win::GetVersion() == base::win::VERSION_PRE_XP) michael@0: break; michael@0: michael@0: jeli.BasicLimitInformation.LimitFlags |= michael@0: JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; michael@0: break; michael@0: } michael@0: default: { michael@0: return ERROR_BAD_ARGUMENTS; michael@0: } michael@0: } michael@0: michael@0: if (FALSE == ::SetInformationJobObject(job_handle_, michael@0: JobObjectExtendedLimitInformation, michael@0: &jeli, michael@0: sizeof(jeli))) { michael@0: return ::GetLastError(); michael@0: } michael@0: michael@0: jbur.UIRestrictionsClass = jbur.UIRestrictionsClass & (~ui_exceptions); michael@0: if (FALSE == ::SetInformationJobObject(job_handle_, michael@0: JobObjectBasicUIRestrictions, michael@0: &jbur, michael@0: sizeof(jbur))) { michael@0: return ::GetLastError(); michael@0: } michael@0: michael@0: return ERROR_SUCCESS; michael@0: } michael@0: michael@0: DWORD Job::UserHandleGrantAccess(HANDLE handle) { michael@0: if (!job_handle_) michael@0: return ERROR_NO_DATA; michael@0: michael@0: if (!::UserHandleGrantAccess(handle, michael@0: job_handle_, michael@0: TRUE)) { // Access allowed. michael@0: return ::GetLastError(); michael@0: } michael@0: michael@0: return ERROR_SUCCESS; michael@0: } michael@0: michael@0: HANDLE Job::Detach() { michael@0: HANDLE handle_temp = job_handle_; michael@0: job_handle_ = NULL; michael@0: return handle_temp; michael@0: } michael@0: michael@0: DWORD Job::AssignProcessToJob(HANDLE process_handle) { michael@0: if (!job_handle_) michael@0: return ERROR_NO_DATA; michael@0: michael@0: if (FALSE == ::AssignProcessToJobObject(job_handle_, process_handle)) michael@0: return ::GetLastError(); michael@0: michael@0: return ERROR_SUCCESS; michael@0: } michael@0: michael@0: } // namespace sandbox