一些互联网搜索0x555555554000 给出了提示:ThreadSanitizer 存在问题https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual
问:当我运行程序时,它说:致命:ThreadSanitizer 无法映射影子内存(某些内容映射在 0x555555554000 < 0x7cf000000000)。该怎么办?您需要启用 ASLR:
$ echo 2 >/proc/sys/kernel/randomize_va_space
这可能会在未来的内核中修复,请参阅https://bugzilla.kernel.org/show_bug.cgi?id=66721
...
$ gdb -ex 'set disable-randomization off' --args ./a.out
和https://lwn.net/Articles/730120/ “稳定的内核更新”。发布于 2017 年 8 月 7 日 20:40 UTC(星期一),由 hmh(订阅者)https://marc.info/?t=150213704600001&r=1&w=2
(https://patchwork.kernel.org/patch/9886105/)提交c715b72c1ba4 )
将 x86_64 和 arm64 PIE 基础从 0x555555554000 移动到 0x000100000000 破坏了 AddressSanitizer。这是对以下内容的部分还原:
还原的代码是:
b/arch/arm64/include/asm/elf.h
/*
* This is the base location for PIE (ET_DYN with INTERP) loads. On
- * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * 64-bit, this is above 4GB to leave the entire 32-bit address * space open for things that want to use the area for 32-bit pointers. */
-#define ELF_ET_DYN_BASE 0x100000000UL
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3)
+++ b/arch/x86/include/asm/elf.h
/*
* This is the base location for PIE (ET_DYN with INTERP) loads. On
- * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * 64-bit, this is above 4GB to leave the entire 32-bit address
* space open for things that want to use the area for 32-bit pointers.
*/
#define ELF_ET_DYN_BASE (mmap_is_ia32() ? 0x000400000UL : \
- 0x100000000UL)
+ (TASK_SIZE / 3 * 2))
因此,0x555555554000 与ELF_ET_DYN_BASE
宏相关(在fs/binfmt_elf.c 中引用ET_DYN
为未随机化load_bias
),对于 x86_64 和 arm64,它就像 TASK_SIZE 的 2/3。如果没有CONFIG_X86_32
,x86_64 的 TASK_SIZE 为2^47 - 一页arch/x86/include/asm/processor.h
/*
* User space process size. 47bits minus one guard page. The guard
* page is necessary on Intel CPUs: if a SYSCALL instruction is at
* the highest possible canonical userspace address, then that
* syscall will enter the kernel with a non-canonical return
* address, and SYSRET will explode dangerously. We avoid this
* particular problem by preventing anything from being mapped
* at the maximum canonical address.
*/
#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE)
旧版本:
/*
* User space process size. 47bits minus one guard page.
*/
#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE)
较新的版本还支持5level和__VIRTUAL_MASK_SHIFT
56 位- v4.17/source/arch/x86/include/asm/processor.h
(但不想在用户启用之前使用它+ commit b569bab78d8d ".. 并非所有用户空间都准备好处理宽地址")。
因此,0x555555554000 从公式(2^47-1page)*(2/3)(或 2^56 对于较大的系统)向下舍入(按load_bias = ELF_PAGESTART(load_bias - vaddr);
,vaddr 为零):
$ echo 'obase=16; (2^47-4096)/3*2'| bc -q
555555554AAA
$ echo 'obase=16; (2^56-4096)/3*2'| bc -q
AAAAAAAAAAA000
2/3 * TASK_SIZE 的一些历史记录:
几乎所有的拱门都将 ELF_ET_DYN_BASE 定义为 TASK_SIZE 的 2/3。尽管似乎某些架构以错误的方式执行此操作。问题是 2*TASK_SIZE 可能会溢出 32 位,因此真正的 ELF_ET_DYN_BASE 会出错。通过在乘法之前除以 TASK_SIZE 来修复此溢出:(TASK_SIZE / 3 * 2)
- 在 4.x、3.y、2.6.z 中相同(davej-history git repo 在哪里?存档和在 or.cz)2.4.z,... 在1997 年 9 月 6 日的 2.1.54 中添加
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
+/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ use of this is to invoke "./ld.so someprog" to test out a new version of
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)