1*7c3d14c8STreehugger Robot //===-- msan_poisoning.cc ---------------------------------------*- C++ -*-===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is a part of MemorySanitizer.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
13*7c3d14c8STreehugger Robot
14*7c3d14c8STreehugger Robot #include "msan_poisoning.h"
15*7c3d14c8STreehugger Robot
16*7c3d14c8STreehugger Robot #include "interception/interception.h"
17*7c3d14c8STreehugger Robot #include "msan_origin.h"
18*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common.h"
19*7c3d14c8STreehugger Robot
20*7c3d14c8STreehugger Robot DECLARE_REAL(void *, memset, void *dest, int c, uptr n)
21*7c3d14c8STreehugger Robot DECLARE_REAL(void *, memcpy, void *dest, const void *src, uptr n)
22*7c3d14c8STreehugger Robot DECLARE_REAL(void *, memmove, void *dest, const void *src, uptr n)
23*7c3d14c8STreehugger Robot
24*7c3d14c8STreehugger Robot namespace __msan {
25*7c3d14c8STreehugger Robot
GetOriginIfPoisoned(uptr addr,uptr size)26*7c3d14c8STreehugger Robot u32 GetOriginIfPoisoned(uptr addr, uptr size) {
27*7c3d14c8STreehugger Robot unsigned char *s = (unsigned char *)MEM_TO_SHADOW(addr);
28*7c3d14c8STreehugger Robot for (uptr i = 0; i < size; ++i)
29*7c3d14c8STreehugger Robot if (s[i]) return *(u32 *)SHADOW_TO_ORIGIN(((uptr)s + i) & ~3UL);
30*7c3d14c8STreehugger Robot return 0;
31*7c3d14c8STreehugger Robot }
32*7c3d14c8STreehugger Robot
SetOriginIfPoisoned(uptr addr,uptr src_shadow,uptr size,u32 src_origin)33*7c3d14c8STreehugger Robot void SetOriginIfPoisoned(uptr addr, uptr src_shadow, uptr size,
34*7c3d14c8STreehugger Robot u32 src_origin) {
35*7c3d14c8STreehugger Robot uptr dst_s = MEM_TO_SHADOW(addr);
36*7c3d14c8STreehugger Robot uptr src_s = src_shadow;
37*7c3d14c8STreehugger Robot uptr src_s_end = src_s + size;
38*7c3d14c8STreehugger Robot
39*7c3d14c8STreehugger Robot for (; src_s < src_s_end; ++dst_s, ++src_s)
40*7c3d14c8STreehugger Robot if (*(u8 *)src_s) *(u32 *)SHADOW_TO_ORIGIN(dst_s & ~3UL) = src_origin;
41*7c3d14c8STreehugger Robot }
42*7c3d14c8STreehugger Robot
CopyOrigin(const void * dst,const void * src,uptr size,StackTrace * stack)43*7c3d14c8STreehugger Robot void CopyOrigin(const void *dst, const void *src, uptr size,
44*7c3d14c8STreehugger Robot StackTrace *stack) {
45*7c3d14c8STreehugger Robot if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return;
46*7c3d14c8STreehugger Robot
47*7c3d14c8STreehugger Robot uptr d = (uptr)dst;
48*7c3d14c8STreehugger Robot uptr beg = d & ~3UL;
49*7c3d14c8STreehugger Robot // Copy left unaligned origin if that memory is poisoned.
50*7c3d14c8STreehugger Robot if (beg < d) {
51*7c3d14c8STreehugger Robot u32 o = GetOriginIfPoisoned((uptr)src, d - beg);
52*7c3d14c8STreehugger Robot if (o) {
53*7c3d14c8STreehugger Robot if (__msan_get_track_origins() > 1) o = ChainOrigin(o, stack);
54*7c3d14c8STreehugger Robot *(u32 *)MEM_TO_ORIGIN(beg) = o;
55*7c3d14c8STreehugger Robot }
56*7c3d14c8STreehugger Robot beg += 4;
57*7c3d14c8STreehugger Robot }
58*7c3d14c8STreehugger Robot
59*7c3d14c8STreehugger Robot uptr end = (d + size) & ~3UL;
60*7c3d14c8STreehugger Robot // If both ends fall into the same 4-byte slot, we are done.
61*7c3d14c8STreehugger Robot if (end < beg) return;
62*7c3d14c8STreehugger Robot
63*7c3d14c8STreehugger Robot // Copy right unaligned origin if that memory is poisoned.
64*7c3d14c8STreehugger Robot if (end < d + size) {
65*7c3d14c8STreehugger Robot u32 o = GetOriginIfPoisoned((uptr)src + (end - d), (d + size) - end);
66*7c3d14c8STreehugger Robot if (o) {
67*7c3d14c8STreehugger Robot if (__msan_get_track_origins() > 1) o = ChainOrigin(o, stack);
68*7c3d14c8STreehugger Robot *(u32 *)MEM_TO_ORIGIN(end) = o;
69*7c3d14c8STreehugger Robot }
70*7c3d14c8STreehugger Robot }
71*7c3d14c8STreehugger Robot
72*7c3d14c8STreehugger Robot if (beg < end) {
73*7c3d14c8STreehugger Robot // Align src up.
74*7c3d14c8STreehugger Robot uptr s = ((uptr)src + 3) & ~3UL;
75*7c3d14c8STreehugger Robot // FIXME: factor out to msan_copy_origin_aligned
76*7c3d14c8STreehugger Robot if (__msan_get_track_origins() > 1) {
77*7c3d14c8STreehugger Robot u32 *src = (u32 *)MEM_TO_ORIGIN(s);
78*7c3d14c8STreehugger Robot u32 *src_s = (u32 *)MEM_TO_SHADOW(s);
79*7c3d14c8STreehugger Robot u32 *src_end = (u32 *)MEM_TO_ORIGIN(s + (end - beg));
80*7c3d14c8STreehugger Robot u32 *dst = (u32 *)MEM_TO_ORIGIN(beg);
81*7c3d14c8STreehugger Robot u32 src_o = 0;
82*7c3d14c8STreehugger Robot u32 dst_o = 0;
83*7c3d14c8STreehugger Robot for (; src < src_end; ++src, ++src_s, ++dst) {
84*7c3d14c8STreehugger Robot if (!*src_s) continue;
85*7c3d14c8STreehugger Robot if (*src != src_o) {
86*7c3d14c8STreehugger Robot src_o = *src;
87*7c3d14c8STreehugger Robot dst_o = ChainOrigin(src_o, stack);
88*7c3d14c8STreehugger Robot }
89*7c3d14c8STreehugger Robot *dst = dst_o;
90*7c3d14c8STreehugger Robot }
91*7c3d14c8STreehugger Robot } else {
92*7c3d14c8STreehugger Robot REAL(memcpy)((void *)MEM_TO_ORIGIN(beg), (void *)MEM_TO_ORIGIN(s),
93*7c3d14c8STreehugger Robot end - beg);
94*7c3d14c8STreehugger Robot }
95*7c3d14c8STreehugger Robot }
96*7c3d14c8STreehugger Robot }
97*7c3d14c8STreehugger Robot
MoveShadowAndOrigin(const void * dst,const void * src,uptr size,StackTrace * stack)98*7c3d14c8STreehugger Robot void MoveShadowAndOrigin(const void *dst, const void *src, uptr size,
99*7c3d14c8STreehugger Robot StackTrace *stack) {
100*7c3d14c8STreehugger Robot if (!MEM_IS_APP(dst)) return;
101*7c3d14c8STreehugger Robot if (!MEM_IS_APP(src)) return;
102*7c3d14c8STreehugger Robot if (src == dst) return;
103*7c3d14c8STreehugger Robot REAL(memmove)((void *)MEM_TO_SHADOW((uptr)dst),
104*7c3d14c8STreehugger Robot (void *)MEM_TO_SHADOW((uptr)src), size);
105*7c3d14c8STreehugger Robot if (__msan_get_track_origins()) CopyOrigin(dst, src, size, stack);
106*7c3d14c8STreehugger Robot }
107*7c3d14c8STreehugger Robot
CopyShadowAndOrigin(const void * dst,const void * src,uptr size,StackTrace * stack)108*7c3d14c8STreehugger Robot void CopyShadowAndOrigin(const void *dst, const void *src, uptr size,
109*7c3d14c8STreehugger Robot StackTrace *stack) {
110*7c3d14c8STreehugger Robot if (!MEM_IS_APP(dst)) return;
111*7c3d14c8STreehugger Robot if (!MEM_IS_APP(src)) return;
112*7c3d14c8STreehugger Robot REAL(memcpy)((void *)MEM_TO_SHADOW((uptr)dst),
113*7c3d14c8STreehugger Robot (void *)MEM_TO_SHADOW((uptr)src), size);
114*7c3d14c8STreehugger Robot if (__msan_get_track_origins()) CopyOrigin(dst, src, size, stack);
115*7c3d14c8STreehugger Robot }
116*7c3d14c8STreehugger Robot
CopyMemory(void * dst,const void * src,uptr size,StackTrace * stack)117*7c3d14c8STreehugger Robot void CopyMemory(void *dst, const void *src, uptr size, StackTrace *stack) {
118*7c3d14c8STreehugger Robot REAL(memcpy)(dst, src, size);
119*7c3d14c8STreehugger Robot CopyShadowAndOrigin(dst, src, size, stack);
120*7c3d14c8STreehugger Robot }
121*7c3d14c8STreehugger Robot
SetShadow(const void * ptr,uptr size,u8 value)122*7c3d14c8STreehugger Robot void SetShadow(const void *ptr, uptr size, u8 value) {
123*7c3d14c8STreehugger Robot uptr PageSize = GetPageSizeCached();
124*7c3d14c8STreehugger Robot uptr shadow_beg = MEM_TO_SHADOW(ptr);
125*7c3d14c8STreehugger Robot uptr shadow_end = shadow_beg + size;
126*7c3d14c8STreehugger Robot if (value ||
127*7c3d14c8STreehugger Robot shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
128*7c3d14c8STreehugger Robot REAL(memset)((void *)shadow_beg, value, shadow_end - shadow_beg);
129*7c3d14c8STreehugger Robot } else {
130*7c3d14c8STreehugger Robot uptr page_beg = RoundUpTo(shadow_beg, PageSize);
131*7c3d14c8STreehugger Robot uptr page_end = RoundDownTo(shadow_end, PageSize);
132*7c3d14c8STreehugger Robot
133*7c3d14c8STreehugger Robot if (page_beg >= page_end) {
134*7c3d14c8STreehugger Robot REAL(memset)((void *)shadow_beg, 0, shadow_end - shadow_beg);
135*7c3d14c8STreehugger Robot } else {
136*7c3d14c8STreehugger Robot if (page_beg != shadow_beg) {
137*7c3d14c8STreehugger Robot REAL(memset)((void *)shadow_beg, 0, page_beg - shadow_beg);
138*7c3d14c8STreehugger Robot }
139*7c3d14c8STreehugger Robot if (page_end != shadow_end) {
140*7c3d14c8STreehugger Robot REAL(memset)((void *)page_end, 0, shadow_end - page_end);
141*7c3d14c8STreehugger Robot }
142*7c3d14c8STreehugger Robot MmapFixedNoReserve(page_beg, page_end - page_beg);
143*7c3d14c8STreehugger Robot }
144*7c3d14c8STreehugger Robot }
145*7c3d14c8STreehugger Robot }
146*7c3d14c8STreehugger Robot
SetOrigin(const void * dst,uptr size,u32 origin)147*7c3d14c8STreehugger Robot void SetOrigin(const void *dst, uptr size, u32 origin) {
148*7c3d14c8STreehugger Robot // Origin mapping is 4 bytes per 4 bytes of application memory.
149*7c3d14c8STreehugger Robot // Here we extend the range such that its left and right bounds are both
150*7c3d14c8STreehugger Robot // 4 byte aligned.
151*7c3d14c8STreehugger Robot uptr x = MEM_TO_ORIGIN((uptr)dst);
152*7c3d14c8STreehugger Robot uptr beg = x & ~3UL; // align down.
153*7c3d14c8STreehugger Robot uptr end = (x + size + 3) & ~3UL; // align up.
154*7c3d14c8STreehugger Robot u64 origin64 = ((u64)origin << 32) | origin;
155*7c3d14c8STreehugger Robot // This is like memset, but the value is 32-bit. We unroll by 2 to write
156*7c3d14c8STreehugger Robot // 64 bits at once. May want to unroll further to get 128-bit stores.
157*7c3d14c8STreehugger Robot if (beg & 7ULL) {
158*7c3d14c8STreehugger Robot *(u32 *)beg = origin;
159*7c3d14c8STreehugger Robot beg += 4;
160*7c3d14c8STreehugger Robot }
161*7c3d14c8STreehugger Robot for (uptr addr = beg; addr < (end & ~7UL); addr += 8) *(u64 *)addr = origin64;
162*7c3d14c8STreehugger Robot if (end & 7ULL) *(u32 *)(end - 4) = origin;
163*7c3d14c8STreehugger Robot }
164*7c3d14c8STreehugger Robot
PoisonMemory(const void * dst,uptr size,StackTrace * stack)165*7c3d14c8STreehugger Robot void PoisonMemory(const void *dst, uptr size, StackTrace *stack) {
166*7c3d14c8STreehugger Robot SetShadow(dst, size, (u8)-1);
167*7c3d14c8STreehugger Robot
168*7c3d14c8STreehugger Robot if (__msan_get_track_origins()) {
169*7c3d14c8STreehugger Robot Origin o = Origin::CreateHeapOrigin(stack);
170*7c3d14c8STreehugger Robot SetOrigin(dst, size, o.raw_id());
171*7c3d14c8STreehugger Robot }
172*7c3d14c8STreehugger Robot }
173*7c3d14c8STreehugger Robot
174*7c3d14c8STreehugger Robot } // namespace __msan
175