Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome_elf / ntdll_cache.cc
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/ntdll_cache.h"
6
7 #include <stdint.h>
8 #include <windows.h>
9
10 #include "base/basictypes.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/win/pe_image.h"
13 #include "chrome_elf/thunk_getter.h"
14 #include "sandbox/win/src/interception_internal.h"
15 #include "sandbox/win/src/internal_types.h"
16 #include "sandbox/win/src/service_resolver.h"
17
18 FunctionLookupTable g_ntdll_lookup;
19
20 // Allocate storage for thunks in a page of this module to save on doing
21 // an extra allocation at run time.
22 #pragma section(".crthunk",read,execute)
23 __declspec(allocate(".crthunk")) sandbox::ThunkData g_nt_thunk_storage;
24
25
26
27 namespace {
28
29 bool EnumExportsCallback(const base::win::PEImage& image,
30                          DWORD ordinal,
31                          DWORD hint,
32                          LPCSTR name,
33                          PVOID function_addr,
34                          LPCSTR forward,
35                          PVOID cookie) {
36   // Our lookup only cares about named functions that are in ntdll, so skip
37   // unnamed or forwarded exports.
38   if (name && function_addr)
39     g_ntdll_lookup[std::string(name)] = function_addr;
40
41   return true;
42 }
43
44 }  // namespace
45
46 void InitCache() {
47   HMODULE ntdll_handle = ::GetModuleHandle(L"ntdll.dll");
48
49   base::win::PEImage ntdll_image(ntdll_handle);
50
51   ntdll_image.EnumExports(EnumExportsCallback, NULL);
52
53   // If ntdll has already been patched, don't copy it.
54   const bool kRelaxed = false;
55
56   // Create a thunk via the appropriate ServiceResolver instance.
57   scoped_ptr<sandbox::ServiceResolverThunk> thunk(GetThunk(kRelaxed));
58
59   if (thunk.get()) {
60     BYTE* thunk_storage = reinterpret_cast<BYTE*>(&g_nt_thunk_storage);
61
62     // Mark the thunk storage as readable and writeable, since we
63     // are ready to write to it.
64     DWORD old_protect = 0;
65     if (!::VirtualProtect(&g_nt_thunk_storage,
66                           sizeof(g_nt_thunk_storage),
67                           PAGE_EXECUTE_READWRITE,
68                           &old_protect)) {
69       return;
70     }
71
72     size_t storage_used = 0;
73     NTSTATUS ret = thunk->CopyThunk(::GetModuleHandle(sandbox::kNtdllName),
74                                     "NtCreateFile",
75                                     thunk_storage,
76                                     sizeof(sandbox::ThunkData),
77                                     &storage_used);
78
79     if (!NT_SUCCESS(ret)) {
80       memset(&g_nt_thunk_storage, 0, sizeof(g_nt_thunk_storage));
81     }
82
83     // Ensure that the pointer to the old function can't be changed.
84     ::VirtualProtect(&g_nt_thunk_storage,
85                      sizeof(g_nt_thunk_storage),
86                      PAGE_EXECUTE_READ,
87                      &old_protect);
88   }
89 }