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,
     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