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