1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares a helper class for use in performing hot-patching operations.
16 : // The class takes care of modifying page protections as the patcher works.
17 :
18 : #ifndef SYZYGY_AGENT_ASAN_SCOPED_PAGE_PROTECTIONS_H_
19 : #define SYZYGY_AGENT_ASAN_SCOPED_PAGE_PROTECTIONS_H_
20 :
21 : #include <windows.h>
22 : #include <map>
23 : #include "base/callback.h"
24 : #include "base/macros.h"
25 :
26 : namespace agent {
27 : namespace asan {
28 :
29 : // Helper class for managing page protections during hot-patching.
30 : // Notice that modifying page protections is inherently racy. This class
31 : // performs no locking. It's wise to call this function from under a lock
32 : // that prevents concurrent patching on the same module, and the caller must
33 : // guarantee that the underlying pages are not unloaded during patching.
34 : class ScopedPageProtections {
35 : public:
36 : // Optional callback for testing. Notifies of pages whose protections have
37 : // just been removed.
38 : using OnUnprotectCallback = base::Callback<void(void* /* page */,
39 : DWORD /* old_prot */)>;
40 :
41 E : ScopedPageProtections() {}
42 : ~ScopedPageProtections();
43 :
44 : // Makes the page(s) containing @p size bytes starting at @p addr writable.
45 : // @param addr The address to be written.
46 : // @param size The number of bytes to be written.
47 : // @returns true on success, false otherwise.
48 : bool EnsureContainingPagesWritable(void* addr, size_t size);
49 :
50 : // Restores all page protections that have been modified. This is
51 : // automatically invoked on destruction. Specifically remembers pages for
52 : // which restoring protections failed. Repeated calls to this function
53 : // will try again for those pages.
54 : // @returns true on success, false otherwise.
55 : bool RestorePageProtections();
56 :
57 : // Allows settings a callback as a testing seam.
58 E : void set_on_unprotect(OnUnprotectCallback on_unprotect) {
59 E : on_unprotect_ = on_unprotect;
60 E : }
61 :
62 : private:
63 : // Helper function for EnsureContainingPagesWritable.
64 : // @pre page Points to the beginning of a page.
65 : // @param page The address of the page to make writable.
66 : bool EnsurePageWritable(void* page);
67 :
68 : using UnprotectedPages = std::map<void*, DWORD>;
69 :
70 : // Stores the pages unprotected with their original settings.
71 : UnprotectedPages unprotected_pages_;
72 :
73 : // Optional callback.
74 : OnUnprotectCallback on_unprotect_;
75 :
76 : DISALLOW_COPY_AND_ASSIGN(ScopedPageProtections);
77 : };
78 :
79 : } // namespace asan
80 : } // namespace agent
81 :
82 : #endif // SYZYGY_AGENT_ASAN_SCOPED_PAGE_PROTECTIONS_H_
|