Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: chrome_elf/blacklist/blacklist.cc

Issue 107663008: Chrome browser process DLL blacklist. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Greg's feedback. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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 "chrome_elf/blacklist/blacklist.h"
6
7 #include <string.h>
8
9 #include "base/basictypes.h"
10 #include "chrome_elf/blacklist/blacklist_interceptions.h"
11 #include "sandbox/win/src/interception_internal.h"
12 #include "sandbox/win/src/internal_types.h"
13 #include "sandbox/win/src/sandbox_utils.h"
14 #include "sandbox/win/src/service_resolver.h"
15
16 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
17 extern "C" IMAGE_DOS_HEADER __ImageBase;
18
19 namespace blacklist{
20
21 const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount] = {};
22 int g_troublesome_dlls_cur_index = 0;
23
24 const wchar_t kRegistryBeaconPath[] = L"SOFTWARE\\Google\\Chrome\\BLBeacon";
25
26 } // namespace blacklist
27
28 // Allocate storage for thunks in a RWX page of this module to save on doing
29 // an extra allocation at run time.
30 #pragma section(".crthunk",read,write,execute)
31 __declspec(allocate(".crthunk")) sandbox::ThunkData g_thunk_storage;
32
33 namespace {
34
35 enum Version {
36 VERSION_PRE_XP_SP2 = 0, // Not supported.
37 VERSION_XP_SP2,
38 VERSION_SERVER_2003, // Also includes XP Pro x64 and Server 2003 R2.
39 VERSION_VISTA, // Also includes Windows Server 2008.
40 VERSION_WIN7, // Also includes Windows Server 2008 R2.
41 VERSION_WIN8, // Also includes Windows Server 2012.
42 VERSION_WIN8_1, // Code named Windows Blue
rvargas (doing something else) 2013/12/17 22:09:27 nit: the code name seems pointless at this point
robertshield 2013/12/18 02:34:43 Done.
43 VERSION_WIN_LAST, // Indicates error condition.
44 };
45
46 // Whether a process is running under WOW64 (the wrapper that allows 32-bit
47 // processes to run on 64-bit versions of Windows). This will return
48 // WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit
49 // Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g.
50 // the process does not have sufficient access rights to determine this.
51 enum WOW64Status {
52 WOW64_DISABLED,
53 WOW64_ENABLED,
54 WOW64_UNKNOWN,
55 };
56
57 WOW64Status GetWOW64StatusForCurrentProcess() {
58 typedef BOOL (WINAPI* IsWow64ProcessFunc)(HANDLE, PBOOL);
59 IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>(
60 GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"));
61 if (!is_wow64_process)
62 return WOW64_DISABLED;
63 BOOL is_wow64 = FALSE;
64 if (!(*is_wow64_process)(GetCurrentProcess(), &is_wow64))
65 return WOW64_UNKNOWN;
66 return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED;
67 }
68
69 class OSInfo {
70 public:
71 struct VersionNumber {
72 int major;
73 int minor;
74 int build;
75 };
76
77 struct ServicePack {
78 int major;
79 int minor;
80 };
81
82 OSInfo() {
83 OSVERSIONINFOEX version_info = { sizeof(version_info) };
84 GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info));
85 version_number_.major = version_info.dwMajorVersion;
86 version_number_.minor = version_info.dwMinorVersion;
87 version_number_.build = version_info.dwBuildNumber;
88 if ((version_number_.major == 5) && (version_number_.minor > 0)) {
89 // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003.
90 version_ = (version_number_.minor == 1) ? VERSION_XP_SP2 :
91 VERSION_SERVER_2003;
92 if (version_ == VERSION_XP_SP2 && version_info.wServicePackMajor < 2)
93 version_ = VERSION_PRE_XP_SP2;
94 } else if (version_number_.major == 6) {
95 switch (version_number_.minor) {
96 case 0:
97 // Treat Windows Server 2008 the same as Windows Vista.
98 version_ = VERSION_VISTA;
99 break;
100 case 1:
101 // Treat Windows Server 2008 R2 the same as Windows 7.
102 version_ = VERSION_WIN7;
103 break;
104 case 2:
105 // Treat Windows Server 2012 the same as Windows 8.
106 version_ = VERSION_WIN8;
107 break;
108 default:
109 version_ = VERSION_WIN8_1;
110 break;
111 }
112 } else if (version_number_.major > 6) {
113 version_ = VERSION_WIN_LAST;
114 } else {
115 version_ = VERSION_PRE_XP_SP2;
116 }
117
118 service_pack_.major = version_info.wServicePackMajor;
119 service_pack_.minor = version_info.wServicePackMinor;
120 }
121
122 Version version() const { return version_; }
123 VersionNumber version_number() const { return version_number_; }
124 ServicePack service_pack() const { return service_pack_; }
125
126 private:
127 Version version_;
128 VersionNumber version_number_;
129 ServicePack service_pack_;
130
131 DISALLOW_COPY_AND_ASSIGN(OSInfo);
132 };
133
134 bool IsNonBrowserProcess() {
135 wchar_t* command_line = GetCommandLine();
136 return (command_line && wcsstr(command_line, L"--type"));
137 }
138
139 } // namespace
140
141 namespace blacklist {
142
143 bool CreateBeacon() {
144 HKEY beacon_key = 0;
rvargas (doing something else) 2013/12/17 22:09:27 nit: NULL
robertshield 2013/12/18 02:34:43 Done.
145 DWORD disposition = 0;
146 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER,
147 kRegistryBeaconPath,
148 0,
149 NULL,
150 0,
151 KEY_WRITE,
152 NULL,
153 &beacon_key,
154 &disposition);
155 bool success = (result == ERROR_SUCCESS &&
156 disposition != REG_OPENED_EXISTING_KEY);
157 ::RegCloseKey(beacon_key);
rvargas (doing something else) 2013/12/17 22:09:27 Only close the key on ERROR_SUCCESS
robertshield 2013/12/18 02:34:43 Done.
158 return success;
159 }
160
161 bool ClearBeacon() {
162 LONG result = ::RegDeleteKey(HKEY_CURRENT_USER, kRegistryBeaconPath);
163 return (result == ERROR_SUCCESS);
164 }
165
166 // Adds the given dll name to the blacklist.
rvargas (doing something else) 2013/12/17 22:09:27 drop the comment
robertshield 2013/12/18 02:34:43 Done.
167 bool AddDllToBlacklist(const wchar_t* dll_name) {
168 if (g_troublesome_dlls_cur_index >= kTroublesomeDllsMaxCount)
169 return false;
170 for (int i = 0; i < g_troublesome_dlls_cur_index; ++i) {
171 if (!wcscmp(g_troublesome_dlls[i], dll_name))
172 return true;
173 }
174
175 // Copy string to blacklist.
176 wchar_t* str_buffer = new wchar_t[wcslen(dll_name) + 1];
177 wcscpy(str_buffer, dll_name);
178
179 g_troublesome_dlls[g_troublesome_dlls_cur_index] = str_buffer;
180 g_troublesome_dlls_cur_index++;
181 return true;
182 }
183
184 // Removes the given dll name from the blacklist.
rvargas (doing something else) 2013/12/17 22:09:27 ditto
robertshield 2013/12/18 02:34:43 Done.
185 bool RemoveDllFromBlacklist(const wchar_t* dll_name) {
186 for (int i = 0; i < g_troublesome_dlls_cur_index; ++i) {
187 if (!wcscmp(g_troublesome_dlls[i], dll_name)) {
188 // Found the thing to remove. Delete it then replace it with the last
189 // element.
190 g_troublesome_dlls_cur_index--;
191 delete[] g_troublesome_dlls[i];
192 g_troublesome_dlls[i] = g_troublesome_dlls[g_troublesome_dlls_cur_index];
193 g_troublesome_dlls[g_troublesome_dlls_cur_index] = NULL;
194 return true;
195 }
196 }
197 return false;
198 }
199
200 bool Initialize(bool force) {
201 #if defined(_WIN64)
202 // TODO(robertshield): Implement 64-bit support by providing 64-bit
203 // interceptors.
204 return false;
205 #endif
206
207 // Check to see if this is a non-browser process, abort if so.
208 if (IsNonBrowserProcess())
209 return false;
210
211 // Check to see if a beacon is present, abort if so.
212 if (!force && !CreateBeacon())
213 return false;
214
215 // Don't try blacklisting on unsupported OS versions.
216 OSInfo os_info;
217 if (os_info.version() <= VERSION_PRE_XP_SP2)
218 return false;
219
220 // Pseudo-handle, no need to close.
221 HANDLE current_process = ::GetCurrentProcess();
222
223 // Tells the ServiceResolverThunks to patch already patched functions.
rvargas (doing something else) 2013/12/17 22:09:27 tiny nit: tell the what? :). I think "resolver" is
robertshield 2013/12/18 02:34:43 Done.
224 const bool kRelaxed = true;
225
226 // Create a thunk via the appropriate ServiceResolver instance.
227 sandbox::ServiceResolverThunk* thunk;
228 #if defined(_WIN64)
229 // TODO(robertshield): Use the appropriate thunk for 64-bit support
230 // when said support is implemented.
231 #else
232 if (GetWOW64StatusForCurrentProcess() == WOW64_ENABLED) {
233 if (os_info.version() >= VERSION_WIN8)
234 thunk = new sandbox::Wow64W8ResolverThunk(current_process, kRelaxed);
235 else
236 thunk = new sandbox::Wow64ResolverThunk(current_process, kRelaxed);
237 } else if (os_info.version() >= VERSION_WIN8) {
238 thunk = new sandbox::Win8ResolverThunk(current_process, kRelaxed);
239 } else {
240 thunk = new sandbox::ServiceResolverThunk(current_process, kRelaxed);
241 }
242 #endif
243
244 thunk->AllowLocalPatches();
245
246 // Get ntdll base, target name, interceptor address,
247 NTSTATUS ret = thunk->Setup(::GetModuleHandle(sandbox::kNtdllName),
248 reinterpret_cast<void*>(&__ImageBase),
249 "NtMapViewOfSection",
250 NULL,
251 &blacklist::BlNtMapViewOfSection,
252 reinterpret_cast<BYTE*>(&g_thunk_storage),
253 sizeof(sandbox::ThunkData),
254 NULL);
255
256 delete thunk;
257 return NT_SUCCESS(ret);
258 }
259
260 } // namespace blacklist
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698