<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/114793>114793</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
memset interception in compiler-rt asan is incompatible with ntdll.dll 10.0.26100.2161 from Windows 11 24H2
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
yjugl
</td>
</tr>
</table>
<pre>
ntdll
===
[ntdll.dll 10.0.26100.2161](https://msdl.microsoft.com/download/symbols/ntdll.dll/6C29F8C2263000/ntdll.dll) from Windows 11 24H2 26100.2161 differs from previous versions of ntdll.dll in a subtle way.
Previously RtlDispatchException would almost directly reach into the vectored exception handlers:
```
// ntdll 10.0.19041.5007
push rbp
push rsi
push rdi
push r12
push r13
push r14
push r15
sub rsp, 1D0h
lea rbp, [rsp+40h]
mov qword ptr [rbp+1E0h], rbx
mov rax, qword ptr [ntdll!__security_cookie]
xor rax, rbp
mov qword ptr [rbp+180h], rax
mov rax, qword ptr gs:[60h]
xor ebx, ebx
mov r15, rdx
mov qword ptr [rbp+40h], rdx
mov rsi, rcx
mov byte ptr [rbp], bl
test dword ptr [rax+0BCh], 800000h
jne ntdll!RtlDispatchException+0x687c4
xor r8d, r8d
mov rdx, r15
mov rcx, rsi
call ntdll!RtlpCallVectoredHandlers
```
But now, two buffers of respective sizes 0x58 and 0xD8 are memset to zero before reaching into the vectored exception handlers:
```
// 10.0.26100.2161
ntdll!RtlDispatchException:
push rbp
push rsi
push rdi
push r12
push r13
push r14
push r15
sub rsp, 210h
lea rbp, [rsp+60h]
mov qword ptr [rbp+200h], rbx
mov rax, qword ptr [ntdll!__security_cookie]
xor rax, rbp
mov qword ptr [rbp+1A0h], rax
xor esi, esi
mov r15, rdx
mov rdi, rcx
mov dword ptr [rbp+20h], esi
xor edx, edx
lea rcx, [rbp+50h]
lea r8d, [rsi+50h]
// memset(something, 0, 0x50)
call ntdll!memset$thunk$772440563353939046
xor edx, edx
mov byte ptr [rbp], sil
mov r8d, 0D8h
mov qword ptr [rbp+8], rsi
lea rcx, [rbp+0C0h]
mov qword ptr [rbp+10h], rsi
mov qword ptr [rbp+18h], rsi
mov qword ptr [rbp+48h], rsi
mov qword ptr [rbp+28h], rsi
mov qword ptr [rbp+40h], rsi
// memset(something, 0, 0xD8)
call ntdll!memset$thunk$772440563353939046
mov rax, qword ptr gs:[60h]
test dword ptr [rax+0BCh], 800000h
je ntdll!RtlDispatchException+0xa0
cmp qword ptr [ntdll!RtlpExceptionLog2], rsi
mov byte ptr [rbp], 1
jne ntdll!RtlDispatchException+0x609
xor r8d, r8d
mov rdx, r15
mov rcx, rdi
call ntdll!RtlpCallVectoredHandlers
```
Now let me detail why we care here.
memset interception with ASAN
=====================
When compiler-rt ASAN instrumentation is in place, memset is replaced for instrumentation purposes. So any memset will go through:
```c++
#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
{ \
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
return internal_memset(dst, v, size); \
COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \
if (common_flags()->intercept_intrin) \
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
return REAL(memset)(dst, v, size); \
}
```
Which, after following macros, uses:
```c++
#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) \
do { \
uptr __offset = (uptr)(offset); \
uptr __size = (uptr)(size); \
uptr __bad = 0; \
if (UNLIKELY(__offset > __offset + __size)) { \
GET_STACK_TRACE_FATAL_HERE; \
ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
} \
if (UNLIKELY(!QuickCheckForUnpoisonedRegion(__offset, __size)) && \
(__bad = __asan_region_is_poisoned(__offset, __size))) { \
AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
bool suppressed = false; \
if (_ctx) { \
suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
if (!suppressed && HaveStackTraceBasedSuppressions()) { \
GET_STACK_TRACE_FATAL_HERE; \
suppressed = IsStackTraceSuppressed(&stack); \
} \
} \
if (!suppressed) { \
GET_CURRENT_PC_BP_SP; \
ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false); \
} \
} \
} while (0)
```
In particular, `__asan_region_is_poisoned` will access the shadow memory corresponding to the region that we memset, in order to check if the region is poisoned.
Shadow memory lazy commit on Windows
============================
On Windows, shadow memory pages are first allocated as `MEM_RESERVE`. They are dynamically turned to `MEM_COMMIT` on demand -- meaning that we rely on an exception handler `ShadowExceptionHandler` to change the status of the page when we fail to access a reserved shadow memory page because it is not yet commited.
Putting it together
============
The memset interception in ASAN is incompatible with ntdll 10.0.26100.2161. As soon as a first access violation gets raised because a shadow memory page is reserved but not committed, we immediately reach a new call to memset before we get a chance to reach the `ShadowExceptionHandler`. The new call to memset itself triggers a new access violation and a new call to memset, etc. This is a neverending cycle, until eventually we overflow the stack.
```c++
# Child-SP RetAddr Call Site
00 0000003e`f3000fa0 00007ffb`03adf0da clang_rt_asan_dynamic_x86_64!__asan_wrap_memset+0x18e [/builds/worker/fetches/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc @ 87]
01 0000003e`f3001830 00007ffb`03c236de ntdll!RtlDispatchException+0x4a
02 0000003e`f3001a80 00007ffa`8c4c8632 ntdll!KiUserExceptionDispatch+0x2e
03 (Inline Function) --------`-------- clang_rt_asan_dynamic_x86_64!__asan::AddressIsPoisoned+0xe [/builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_mapping.h @ 395]
04 0000003e`f3002180 00007ffa`8c4c56a3 clang_rt_asan_dynamic_x86_64!__asan_region_is_poisoned+0xf2 [/builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_poisoning.cpp @ 189]
05 0000003e`f30021e0 00007ffb`03adf0da clang_rt_asan_dynamic_x86_64!__asan_wrap_memset+0x193 [/builds/worker/fetches/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc @ 87]
06 0000003e`f3002a70 00007ffb`03c236de ntdll!RtlDispatchException+0x4a
07 0000003e`f3002cc0 00007ffa`8c4c8632 ntdll!KiUserExceptionDispatch+0x2e
08 (Inline Function) --------`-------- clang_rt_asan_dynamic_x86_64!__asan::AddressIsPoisoned+0xe [/builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_mapping.h @ 395]
09 0000003e`f30033c0 00007ffa`8c4c56a3 clang_rt_asan_dynamic_x86_64!__asan_region_is_poisoned+0xf2 [/builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_poisoning.cpp @ 189]
// ...
```
Related Firefox bug [here](https://bugzilla.mozilla.org/show_bug.cgi?id=1926680).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzcWltz4jgW_jXKy6mmbJnrQx64dlPTnc4CPV2zLy5hH2NNC4uV5AD967ck22DASSczedhZikqCrHP7zkXnKDCt-SZDvCedEelM7lhuUqnuj3_mG3G3lvHxPjOxEMSbEG9Igkn5Lj4WPzsjt6UVCwG-1_JatOt7Xov6XZ90JoT2U2N2mgRDQmeEzrY6Fq0tj5TUMjGtSG4JncVynwnJYkJn-rhdS6EJnZ3YEjrrjulg1h9T2g08z7t8OIBEyS1851ks9xp8H2j7E4WzGhDzJEGli307hU9c5hqeUGkuMw0ygbMJPAMGOl8bgbBnx1bd1seSVBxhYcSE6x0zUTo9RLgzXGawl7mIgYmt1AZirjAy4ggKWZQCz4wEkyI8YWSkwhjwRJeyLBaoHEh1aLte-S4-OvwKVQuk_YHX9lsdz-sVO3a5TgEA1Hp3taD51UJcX1A-vXrsB9cL7euFTrGg8zUUInaEjsGfeGnxQCBzitAxkM7IPR61vdTGhHu-lU-O8D97qWLYGeW2WYKRPy320TGo9eFyu2IHu35BVcQo9cNQY5Qrbo5hJOUPjidhB6nq1CeAXlKif1aC_UqJjfNdZ9StGVjJxLXbjHVLLHyWcXz4pR7tsxrXu61b7XpUW18fDdYZFKTrMoUNamMp4ws51pqRNxpXgvqefZV-_DNDqABuinpLeuj2e1H7Cup-7JTrx1dKx4ULqgA6rUfFehWqEROiLng3ZkL8XibPpypjGhPF_RzlBjK5tzzNXsI6L2qATECh3mFk-BOC5j9Rg3fo9IFlMXiHSR-YQtjiVqMBI-EnKglrTKTCIpN5tnm_ZL4umO7Zy3BXbF-Z7JeZ7jL37yV7mejUryd6pUg92buvS3bq_S8k-_A22U_5W2QZVrCelHsmhy3i11l5m3Ol7ZXUE_eT1CJNsOJ-QrlIkxOLTg3l054i9Zwn-NUegDL0ihAntK_lFo0Na0vjuR-HjkfooCEPK6K2SfPsB6HtXo-2216nGwSdYBAMvHb3ZTMqMJrLlObiCsvCEm_ST3_pw37lwApKdwJdweWNX3kEnePh2u-NZ8VbdrfftJu-jfet3q_z-KR_6XGAtzv9TcfjXzmKXnESsbLARtvdLUb14-RE9llu6HMIN4ep_5aT0Ru8z7kYv9O5-CD3INDAFiFGw7iAfXqEPUJkD74UFV70vOVJyDOD6tTncpPCcDl8uJ4L_tq7Ju17ihlEcrvjAtUHZZwU4Jk2Kt9iZpiTz7Vt03eCRWihqVTUoNAtxpBIdUO1y9VOatQtWEpg2bGi23MhYGPPcyXzTfrcuR0ROrLv8vgOYkx4hjD--uXL14dw_rCaLsbTx9XXRfhl-mU5XYXzL4-fCe1Hxvkv1sb-eirK3E-0cwvpjE8p2hvVPwLwBAjtN3B_-Lr6NH_4GM6X4fxhvpoPP8__PZ1YduXrzEahyVVW-C5jIjwVgAZlSDCCy9eZT4MWU_v32bqKc6OdjnWDcZHcbmUWJoJtNKG2_nwgwfQUaSHPjOJZzbLXqfZ9MV9Nw8Xw4eP0Bv4rYy-UKtFaTIfWbZVFg9fCdc2Q9CYvZOH3lEep5ccSgwoSKYTc29Zyy-xobJ_kGp9tIp8JxuF4PF0ubQB-XfxxDYFMktJHhQ1j4Pq74gabEL4wJZYuPt_hdWaa26oahoVSQIKJjQi7WEBeKfsc0K_hbc285Vxz4IX7S6I1ix2Nd7OhCNpvD5_nv00__0Fov6b9tGYKHZWynbzBbWoDfJyuwuVqOP4tXC2G42k4G66Gn8NP08X0RirAAndSmaXNhc0szyJbzJb8J359QpUIO-GcNLFOrWSPgdCuNiz60WQt6U1-YR2h_r9yHv0Ypxj9mEn1LdtJrmWG8QI37nRrFFuYTLuEdq_DqHSTpatQDkOmWRYqxzHkOqxkvMC9wrQpUu1rqFk2r4qIVGOZGTxYvwzDyByqgHh-F6EDmzGnuLtiv5ZSgM53O4VaY2FGwoTGBtcVoIYuARsDAa45zXVNqeXpWcnloj5KFWZs-2w5O8sn1K9LKXzziT3h0kbHSrEIR0xjXInjMivr8Q3UNREvx_DbEvYGhLNmFxhcRfSLPG2E_93X-3Kr82vwzLMhYpEef1sspg-r8HEcjh7D5WNDsFWV4iNmqHg0VUoqQvu7yF0Audm8GN1d-l3U_3rVcPNAEdANdaOhclwt2I_7lAu0Bp7HyMZTcJ7BjinDo1ww5UpW13u-JHS9oldjUYRau_sXnbJY7m37IdURIqkU6p3MYnuSllc0BSMwKTO2yz13KjwDqWJUdmNki5x1So2Ca6hEX3TEywuZgv20grdbbkBm1S30-zTGv-qWv57lWede6LVjG9TuLivhShtgQsiIGYyBaQvzl-mXcDFdThe_T0nXa8EqxaPbHh8ztuV2yjiCbYgwtgCVFLbdmq-sJ2QGMW5ZFsOHD7BFljnIS5AViqPdwbLbizHLqoDwNCiVU4tl63zBsg0W7jXM5O7Ozn6yJsHeTgh7hMROLkZWwcBAoUb1hHEDDrDGiOUagbspIZMGjmhKr1159zE3xl3xGTBygyZF9QZn1hit0tM14sXwxLNyqLFDjB11mOFrgcVQVbvcP98KtmCoQUuLpzW09Gdh9xOXohhvNmg0KMZtEa3sZU1guDmpxGrtLkkrKAy6srBH4NstxpwZPP3_gkGGe3DDp5GVYeW96B6tdGDOdRHaDQWR9dpL7nZh18SYG40iAaP4ZoNKl9JvbLbh16SYu3IykWVvYS7on1BhURmiYyRcrcszwwXgE2YmdwG_R5BlW1UFYPSj9esWHAgNYJxyEX9YPp7r_QLNMI7V1SlgB3ZY2sLraD0P3CWHFyDpekngeV7CirVekqxJ1_MCFideXFzuRYJlm1CZokyW2Roe-t2w23bXom59r9juNO-NvIPfRyCdEaGzdc5FrAmd7aX6gYrQWYImStEuCfG0_bBT8k-MDKGz2iBuH_I1oTPLndBZq0XoTLOMG_4TVViMcg1LYa1d0VahYqjTPNItnkVA2h70e6QzgRIM_xoMvx9cgRHRoBu_4uqlzUqe9IYn6594MtL1-lE76ncDeuL5G_-mUZ3YVfwdW1r5LbAn3DwTdvKqGnN7iH8oX6TrVX--zmt22guGNmJQ67l-PPXCI-_wvu5zWmzZbsezTSt1XggGnZob2teQUf8Wsk6XBa-Mx6YOf-QdEvr-ZhUCrGHRbudM8_uDmmmdW9OwOd3-YqoNgn9GqnVvgGC9v5tqvRueUfQOqdb_P061wTVkQXAL2T8y1cr_O7RarRdmgAUK15bOuMJEHmCdb6yiKSps-v7IOt_85EKw1lYWv6Xa2GRI5T5c55tWtOEkmPGYBBN_QLtdN4K07uL7IB4EA3aH934v8Hq0N6DBXXrvx7Hvx93Ahn6_jUHi9dqdiLG1H_sUsX3H76lH277vtf2g3aG0FfcwoQw92vE9r-1FpO3hlnHRsthZbe641jne-367NwjuBFuj0O77NZTaTsU9JZSSzuRO3TvA1_lGk7YnuDb6zMZwI_D-mRayfkduXfFCO9n0zZzGr8zc5UrcX6K94SbN1-W3dKxmtzHi7LGxUxr8dE__GwAA__-tAa7z">