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.
5 #include "sandbox/win/src/window.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "sandbox/win/src/acl.h"
12 #include "sandbox/win/src/sid.h"
16 // Gets the security attributes of a window object referenced by |handle|. The
17 // lpSecurityDescriptor member of the SECURITY_ATTRIBUTES parameter returned
18 // must be freed using LocalFree by the caller.
19 bool GetSecurityAttributes(HANDLE handle
, SECURITY_ATTRIBUTES
* attributes
) {
20 attributes
->bInheritHandle
= FALSE
;
21 attributes
->nLength
= sizeof(SECURITY_ATTRIBUTES
);
24 DWORD result
= ::GetSecurityInfo(handle
, SE_WINDOW_OBJECT
,
25 DACL_SECURITY_INFORMATION
, NULL
, NULL
, &dacl
,
26 NULL
, &attributes
->lpSecurityDescriptor
);
27 if (ERROR_SUCCESS
== result
)
37 ResultCode
CreateAltWindowStation(HWINSTA
* winsta
) {
38 // Get the security attributes from the current window station; we will
39 // use this as the base security attributes for the new window station.
40 SECURITY_ATTRIBUTES attributes
= {0};
41 if (!GetSecurityAttributes(::GetProcessWindowStation(), &attributes
)) {
42 return SBOX_ERROR_CANNOT_CREATE_WINSTATION
;
45 // Create the window station using NULL for the name to ask the os to
47 *winsta
= ::CreateWindowStationW(
48 NULL
, 0, GENERIC_READ
| WINSTA_CREATEDESKTOP
, &attributes
);
49 LocalFree(attributes
.lpSecurityDescriptor
);
54 return SBOX_ERROR_CANNOT_CREATE_WINSTATION
;
57 ResultCode
CreateAltDesktop(HWINSTA winsta
, HDESK
* desktop
) {
58 base::string16 desktop_name
= L
"sbox_alternate_desktop_";
60 // Append the current PID to the desktop name.
62 _snwprintf_s(buffer
, sizeof(buffer
) / sizeof(wchar_t), L
"0x%X",
63 ::GetCurrentProcessId());
64 desktop_name
+= buffer
;
66 // Get the security attributes from the current desktop, we will use this as
67 // the base security attributes for the new desktop.
68 SECURITY_ATTRIBUTES attributes
= {0};
69 if (!GetSecurityAttributes(GetThreadDesktop(GetCurrentThreadId()),
71 return SBOX_ERROR_CANNOT_CREATE_DESKTOP
;
74 // Back up the current window station, in case we need to switch it.
75 HWINSTA current_winsta
= ::GetProcessWindowStation();
78 // We need to switch to the alternate window station before creating the
80 if (!::SetProcessWindowStation(winsta
)) {
81 ::LocalFree(attributes
.lpSecurityDescriptor
);
82 return SBOX_ERROR_CANNOT_CREATE_DESKTOP
;
86 // Create the destkop.
87 *desktop
= ::CreateDesktop(desktop_name
.c_str(),
91 DESKTOP_CREATEWINDOW
| DESKTOP_READOBJECTS
|
92 READ_CONTROL
| WRITE_DAC
| WRITE_OWNER
,
94 ::LocalFree(attributes
.lpSecurityDescriptor
);
97 // Revert to the right window station.
98 if (!::SetProcessWindowStation(current_winsta
)) {
99 return SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION
;
104 // Replace the DACL on the new Desktop with a reduced privilege version.
105 // We can soft fail on this for now, as it's just an extra mitigation.
106 static const ACCESS_MASK kDesktopDenyMask
= WRITE_DAC
| WRITE_OWNER
|
109 DESKTOP_CREATEWINDOW
|
110 DESKTOP_HOOKCONTROL
|
111 DESKTOP_JOURNALPLAYBACK
|
112 DESKTOP_JOURNALRECORD
|
113 DESKTOP_SWITCHDESKTOP
;
114 AddKnownSidToObject(*desktop
, SE_WINDOW_OBJECT
, Sid(WinRestrictedCodeSid
),
115 DENY_ACCESS
, kDesktopDenyMask
);
119 return SBOX_ERROR_CANNOT_CREATE_DESKTOP
;
122 base::string16
GetWindowObjectName(HANDLE handle
) {
123 // Get the size of the name.
125 ::GetUserObjectInformation(handle
, UOI_NAME
, NULL
, 0, &size
);
129 return base::string16();
132 // Create the buffer that will hold the name.
133 scoped_ptr
<wchar_t[]> name_buffer(new wchar_t[size
]);
135 // Query the name of the object.
136 if (!::GetUserObjectInformation(handle
, UOI_NAME
, name_buffer
.get(), size
,
139 return base::string16();
142 return base::string16(name_buffer
.get());
145 base::string16
GetFullDesktopName(HWINSTA winsta
, HDESK desktop
) {
148 return base::string16();
153 name
= GetWindowObjectName(winsta
);
157 name
+= GetWindowObjectName(desktop
);
161 } // namespace sandbox