Commit cb5f5d00e4 for openssl.org

commit cb5f5d00e49628f1fb8ac25ff37963f25256cb9a
Author: Wojt Janowski <wojt@clinically.com.au>
Date:   Mon Nov 2 08:31:09 2026 +1100

    crypto/armcap.c: require SVE before probing the SVE vector length on AArch64

    OPENSSL_cpuid_setup() calls _armv8_sve_get_vl_bytes(), which executes an
    SVE instruction, whenever ARMV9_SVE2 is set. Linux kernels without commit
    064737920bdb ("arm64: Filter out SVE hwcaps when FEAT_SVE isn't
    implemented") can report HWCAP2_SVE2 without HWCAP_SVE, for example in
    guests on Apple M4, which implements SME but not SVE. On those systems
    the library dies with SIGILL while loading.

    Only probe the vector length when both ARMV8_SVE and ARMV9_SVE2 are set.
    ARMV9_SVE2_POLY1305 is only set inside this block, and the ChaCha20 SVE
    path already checks ARMV8_SVE first, so no SVE code runs without SVE.

    Fixes: 2657697b6d29 "crypto/poly1305: Add SVE2 vector-length agnostic implementation."
    Assisted-by: Amp:claude-opus-5-5
    Reviewed-by: Jakub Zelenka <jakub.zelenka@openssl.foundation>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
    Merge-date: Wed Nov  4 11:15:06 2026
    Merged-from: https://github.com/openssl/openssl/pull/33481

diff --git a/crypto/armcap.c b/crypto/armcap.c
index 5ada5006be..13acb257a3 100644
--- a/crypto/armcap.c
+++ b/crypto/armcap.c
@@ -475,7 +475,12 @@ void OPENSSL_cpuid_setup(void)
             || MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V3)))
         OPENSSL_armcap_P |= ARMV8_HAVE_SHA3_AND_WORTH_USING;

-    if (OPENSSL_armcap_P & ARMV9_SVE2) {
+    /*
+     * _armv8_sve_get_vl_bytes() executes an SVE instruction. Some kernels and
+     * hypervisors report SVE2 without SVE (e.g. guests on Apple M4, which has
+     * SME but no SVE), so require both before probing the vector length.
+     */
+    if ((OPENSSL_armcap_P & ARMV8_SVE) && (OPENSSL_armcap_P & ARMV9_SVE2)) {
         uint64_t vl_bytes = _armv8_sve_get_vl_bytes();

         if (vl_bytes > 16 && (vl_bytes & (vl_bytes - 1)) == 0) {