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