Home | History | Annotate | Download | only in src
      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