fix: Update node's simdutf to 3.2.9 to fix AVX-related crashes (#40446)

Fix: Backport AVX detection fix from simdutf 3.2.9

simdutf < 3.2.9 contains a flawed detection routine to decide whether
AVX and/or AVX2 can be used. In most cases, it works good enough, but
in some corner cases (combination of specific CPU model, microcode
version, operating system and OS configuration), that flawed detection
results in simdutf trying to use AVX/AVX2 although the OS doesn't allow
its use (for example as a mitigation measure against the "gather data
sampling" vulnerability), which then crashes the application with an
illegal instruction error.

This fix is only needed for node < 18.17.0, because later versions use
a simdutf version > 3.2.9.

Cherry-picked and backported from 55b107f609

Signed-off-by: Pascal Ernster <git@hardfalcon.net>
Co-authored-by: Daniel Lemire <daniel@lemire.me>
Co-authored-by: easyaspi314 <easyaspi314@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
Pascal Ernster
2023-12-08 21:34:40 +01:00
committed by GitHub
parent 1813586545
commit eb2173846b
2 changed files with 100 additions and 0 deletions

View File

@@ -45,4 +45,5 @@ net_fix_crash_due_to_simultaneous_close_shutdown_on_js_stream.patch
net_use_asserts_in_js_socket_stream_to_catch_races_in_future.patch
lib_fix_broadcastchannel_initialization_location.patch
win_process_avoid_assert_after_spawning_store_app_4152.patch
fix_backport_avx_detection_fix_from_simdutf_3_2_9.patch
fix_avx_detection.patch

View File

@@ -0,0 +1,99 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Lemire <daniel@lemire.me>
Date: Fri, 12 May 2023 15:20:29 -0400
Subject: Fix: Backport AVX detection fix from simdutf 3.2.9
simdutf < 3.2.9 contains a flawed detection routine to decide whether
AVX and/or AVX2 can be used. In most cases, it works good enough, but
in some corner cases (combination of specific CPU model, microcode
version, operating system and OS configuration), that flawed detection
results in simdutf trying to use AVX/AVX2 although the OS doesn't allow
its use (for example as a mitigation measure against the "gather data
sampling" vulnerability), which then crashes the application with an
illegal instruction error.
This fix is only needed for node < 18.17.0, because later versions use
a simdutf version > 3.2.9.
Cherry-picked and backported from https://github.com/simdutf/simdutf/commit/55b107f609f5f63880db650a92861ae84cb10abe
Co-authored-by: Daniel Lemire <daniel@lemire.me>
Co-authored-by: easyaspi314 <easyaspi314@users.noreply.github.com>
Signed-off-by: Pascal Ernster <git@hardfalcon.net>
diff --git a/deps/simdutf/simdutf.h b/deps/simdutf/simdutf.h
index 80189d316cba8c9127b652da9e0bcb76d5b9eeb4..4e5ce1e26b6b803698e55436ce0c0ab358662c9e 100644
--- a/deps/simdutf/simdutf.h
+++ b/deps/simdutf/simdutf.h
@@ -706,6 +706,7 @@ namespace cpuid_bit {
// EAX = 0x01
constexpr uint32_t pclmulqdq = uint32_t(1) << 1; ///< @private bit 1 of ECX for EAX=0x1
constexpr uint32_t sse42 = uint32_t(1) << 20; ///< @private bit 20 of ECX for EAX=0x1
+ constexpr uint32_t osxsave = (uint32_t(1) << 26) | (uint32_t(1) << 27); ///< @private bits 26+27 of ECX for EAX=0x1
// EAX = 0x7f (Structured Extended Feature Flags), ECX = 0x00 (Sub-leaf)
// See: "Table 3-8. Information Returned by CPUID Instruction"
@@ -731,6 +732,10 @@ namespace cpuid_bit {
namespace edx {
constexpr uint32_t avx512vp2intersect = uint32_t(1) << 8;
}
+ namespace xcr0_bit {
+ constexpr uint64_t avx256_saved = uint64_t(1) << 2; ///< @private bit 2 = AVX
+ constexpr uint64_t avx512_saved = uint64_t(7) << 5; ///< @private bits 5,6,7 = opmask, ZMM_hi256, hi16_ZMM
+ }
}
}
@@ -740,7 +745,7 @@ static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx) {
#if defined(_MSC_VER)
int cpu_info[4];
- __cpuid(cpu_info, *eax);
+ __cpuidex(cpu_info, *eax, *ecx);
*eax = cpu_info[0];
*ebx = cpu_info[1];
*ecx = cpu_info[2];
@@ -758,6 +763,16 @@ static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
#endif
}
+static inline uint64_t xgetbv() {
+ #if defined(_MSC_VER)
+ return _xgetbv(0);
+ #else
+ uint32_t xcr0_lo, xcr0_hi;
+ asm volatile("xgetbv\n\t" : "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0));
+ return xcr0_lo | ((uint64_t)xcr0_hi << 32);
+ #endif
+ }
+
static inline uint32_t detect_supported_architectures() {
uint32_t eax;
uint32_t ebx = 0;
@@ -777,6 +792,16 @@ static inline uint32_t detect_supported_architectures() {
host_isa |= instruction_set::PCLMULQDQ;
}
+ if ((ecx & cpuid_bit::osxsave) != cpuid_bit::osxsave) {
+ return host_isa;
+ }
+
+ // xgetbv for checking if the OS saves registers
+ uint64_t xcr0 = xgetbv();
+
+ if ((xcr0 & cpuid_bit::xcr0_bit::avx256_saved) == 0) {
+ return host_isa;
+ }
// ECX for EAX=0x7
eax = 0x7;
ecx = 0x0; // Sub-leaf = 0
@@ -790,6 +815,9 @@ static inline uint32_t detect_supported_architectures() {
if (ebx & cpuid_bit::ebx::bmi2) {
host_isa |= instruction_set::BMI2;
}
+ if (!((xcr0 & cpuid_bit::xcr0_bit::avx512_saved) == cpuid_bit::xcr0_bit::avx512_saved)) {
+ return host_isa;
+ }
if (ebx & cpuid_bit::ebx::avx512f) {
host_isa |= instruction_set::AVX512F;
}