Skip to content

Commit 694b132

Browse files
authored
[sanitizer_common] Fix edge case for stack mapping parsing (#98381)
On some systems (e.g., at least two AArch64 Linux instances), the process map can have: ``` fffffffdf000-1000000000000 ... [stack] ``` instead of: ``` fffffffdf000- ffffffffffff ``` The stack top value is larger than `GetMaxUserVirtualAddress()`, which violates the precondition that shadow memory calculations expect. This patch fixes the issue by saturating off-by-one values (and also adds checks for more flagrant violations). This fixes an issue that was observed with DFSan on AArch64 Linux (with high-entropy ASLR, resulting in ASLR being disabled on some runs): ``` ==11057==ERROR: DataflowSanitizer failed to allocate 0x1600000800000 (387028101365760) bytes at address 4fffff800000 (errno: 12) ``` (https://lab.llvm.org/staging/#/builders/90/builds/552/steps/9/logs/stdio) This was trying to allocate a shadow at `[0x4fffff800000, 0x4fffff800000 + 0x1600000800000] = [0x4fffff800000, 0x1b00000000000]`. Notice that the end of the shadow region - an invalid value - is equal to `MEM_TO_SHADOW(0x1000000000000)`, where `MEM_TO_SHADOW` is defined as `(mem ^ 0xB00000000000ULL)`.
1 parent 145ae81 commit 694b132

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,19 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
149149
stacksize = kMaxThreadStackSize;
150150
*stack_top = segment.end;
151151
*stack_bottom = segment.end - stacksize;
152+
153+
uptr maxAddr = GetMaxUserVirtualAddress();
154+
// Edge case: the stack mapping on some systems may be off-by-one e.g.,
155+
// fffffffdf000-1000000000000 rw-p 00000000 00:00 0 [stack]
156+
// instead of:
157+
// fffffffdf000- ffffffffffff
158+
// The out-of-range stack_top can result in an invalid shadow address
159+
// calculation, since those usually assume the parameters are in range.
160+
if (*stack_top == maxAddr + 1)
161+
*stack_top = maxAddr;
162+
else
163+
CHECK_LE(*stack_top, maxAddr);
164+
152165
return;
153166
}
154167
uptr stacksize = 0;

0 commit comments

Comments
 (0)