• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
~Job()12 Job::~Job() {
13   if (job_handle_)
14     ::CloseHandle(job_handle_);
15 };
16 
Init(JobLevel security_level,wchar_t * job_name,DWORD ui_exceptions)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 
UserHandleGrantAccess(HANDLE handle)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 
Detach()100 HANDLE Job::Detach() {
101   HANDLE handle_temp = job_handle_;
102   job_handle_ = NULL;
103   return handle_temp;
104 }
105 
AssignProcessToJob(HANDLE process_handle)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