1 : // Copyright 2014 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 : #include "syzygy/agent/asan/memory_interceptors.h"
15 :
16 : #include "base/logging.h"
17 : #include "syzygy/agent/asan/asan_rtl_utils.h"
18 : #include "syzygy/agent/asan/shadow.h"
19 :
20 : using agent::asan::Shadow;
21 :
22 : namespace agent {
23 : namespace asan {
24 :
25 : // Check if the memory location is accessible and report an error on bad memory
26 : // accesses.
27 : // @param location The memory address of the access.
28 : // @param access_mode The mode of the access.
29 : // @param access_size The size of the access.
30 : // @param context The registers context of the access.
31 : void CheckMemoryAccess(void* location,
32 : AccessMode access_mode,
33 : size_t access_size,
34 E : const AsanContext& context) {
35 E : if (!Shadow::IsAccessible(location))
36 E : ReportBadMemoryAccess(location, access_mode, access_size, context);
37 E : }
38 :
39 : // Check if the memory accesses done by a string instructions are valid.
40 : // @param dst The destination memory address of the access.
41 : // @param dst_access_mode The destination mode of the access.
42 : // @param src The source memory address of the access.
43 : // @param src_access_mode The source mode of the access.
44 : // @param length The number of memory accesses.
45 : // @param access_size The size of each the access in byte.
46 : // @param increment The increment to move dst/src after each access.
47 : // @param compare Flag to activate shortcut of the execution on difference.
48 : // @param context The registers context of the access.
49 : void CheckStringsMemoryAccesses(
50 : uint8* dst, AccessMode dst_access_mode,
51 : uint8* src, AccessMode src_access_mode,
52 : uint32 length, size_t access_size, int32 increment, bool compare,
53 E : const AsanContext& context) {
54 E : int32 offset = 0;
55 :
56 E : for (uint32 i = 0; i < length; ++i) {
57 : // Check next memory location at src[offset].
58 E : if (src_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS)
59 E : CheckMemoryAccess(&src[offset], src_access_mode, access_size, context);
60 :
61 : // Check next memory location at dst[offset].
62 E : if (dst_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS)
63 E : CheckMemoryAccess(&dst[offset], dst_access_mode, access_size, context);
64 :
65 : // For CMPS instructions, we shortcut the execution of prefix REPZ when
66 : // memory contents differ.
67 E : if (compare) {
68 E : uint32 src_content = 0;
69 E : uint32 dst_content = 0;
70 E : switch (access_size) {
71 : case 4:
72 E : src_content = *reinterpret_cast<uint32*>(&src[offset]);
73 E : dst_content = *reinterpret_cast<uint32*>(&dst[offset]);
74 E : break;
75 : case 2:
76 E : src_content = *reinterpret_cast<uint16*>(&src[offset]);
77 E : dst_content = *reinterpret_cast<uint16*>(&dst[offset]);
78 E : break;
79 : case 1:
80 E : src_content = *reinterpret_cast<uint8*>(&src[offset]);
81 E : dst_content = *reinterpret_cast<uint8*>(&dst[offset]);
82 E : break;
83 : default:
84 i : NOTREACHED() << "Unexpected access_size.";
85 : break;
86 : }
87 :
88 E : if (src_content != dst_content)
89 E : return;
90 : }
91 :
92 : // Increments offset of dst/src to the next memory location.
93 E : offset += increment;
94 E : }
95 E : }
96 :
97 : } // namespace asan
98 : } // namespace agent
99 :
100 : // Redefine some enums to make them accessible in the inlined assembly.
101 : // @{
102 : enum AccessMode {
103 : AsanReadAccess = agent::asan::ASAN_READ_ACCESS,
104 : AsanWriteAccess = agent::asan::ASAN_WRITE_ACCESS,
105 : AsanUnknownAccess = agent::asan::ASAN_UNKNOWN_ACCESS,
106 : };
107 : // @}
108 :
109 : // The slow path relies on the fact that the shadow memory non accessible byte
110 : // mask has its upper bit set to 1.
111 : COMPILE_ASSERT((agent::asan::kHeapNonAccessibleMarkerMask & (1 << 7)) != 0,
112 : asan_shadow_mask_upper_bit_is_0);
113 :
114 : // Pull in the actual implementation of the accessor stubs.
115 : #include "syzygy/agent/asan/memory_interceptors_gen.cc"
|