Hi. PuTTY 0.83 on arm64 is badly broken, crashing immediately with a SIGILL. It looks like this is a known problem upstream and has been fixed, so I'd like to backport the patch for it. Simon works at ARM on compilers, so I trust that he has this right.
ok? (This is on a Raspberry Pi 3, but I had the same results on other hardware including VMs): $ /usr/local/bin/puttygen --help Illegal instruction (core dumped) $ /usr/local/bin/plink Illegal instruction (core dumped) $ egdb -q --args /usr/local/bin/puttygen --help Reading symbols from /usr/local/bin/puttygen... (No debugging symbols found in /usr/local/bin/puttygen) (gdb) run Starting program: /usr/local/bin/puttygen --help Program received signal SIGILL, Illegal instruction. 0x0000001f2f086480 in enable_dit () (gdb) bt #0 0x0000001f2f086480 in enable_dit () #1 0x0000001f2f079fb0 in main () $ egdb -q /usr/local/bin/plink Reading symbols from /usr/local/bin/plink... (No debugging symbols found in /usr/local/bin/plink) (gdb) run Starting program: /usr/local/bin/plink Program received signal SIGILL, Illegal instruction. 0x00000013e6206e54 in enable_dit () (gdb) bt #0 0x00000013e6206e54 in enable_dit () #1 0x00000013e61bc0a4 in main () With patch: $ /usr/local/bin/plink --version plink: Release 0.83 Build platform: 64-bit Unix Compiler: clang 16.0.6 Source commit: d2c178c49a0ae6fa9ef75ca84fb3c9d0d675ea85 $ /usr/local/bin/plink localhost The host key is not cached for this server: localhost (port 22) You have no guarantee that the server is the computer you think it is. The server's ssh-ed25519 key fingerprint is: ssh-ed25519 255 SHA256:hMEp6fbjRFwJ2njrdT3du0UtPVnxLDJOw96Zff4JTug [etc] Index: Makefile =================================================================== RCS file: /export/cvs/ports/net/putty/Makefile,v diff -u -p -r1.48 Makefile --- Makefile 8 Feb 2025 16:09:47 -0000 1.48 +++ Makefile 16 Mar 2025 22:08:53 -0000 @@ -2,6 +2,7 @@ COMMENT-main= SSH and telnet client COMMENT-gui= PuTTY GUI clients V= 0.83 +REVISION= 0 DISTNAME= putty-$V PKGNAME-main= ${DISTNAME} PKGNAME-gui= ${DISTNAME:S/putty/putty-gui/} Index: patches/patch-arm-enable_dit-sigill =================================================================== RCS file: patches/patch-arm-enable_dit-sigill diff -N patches/patch-arm-enable_dit-sigill --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-arm-enable_dit-sigill 16 Mar 2025 22:46:04 -0000 @@ -0,0 +1,83 @@ +From 965057d6d6c9de9fcf506c75b0a2fad22988c72b Mon Sep 17 00:00:00 2001 +From: Simon Tatham <ana...@pobox.com> +Date: Sat, 15 Feb 2025 15:57:53 +0000 +Subject: [PATCH] Change strategy for the Arm instruction setting DIT. + +Colin Watson reported that a build failure occurred in the AArch64 +Debian build of PuTTY 0.83: + +gcc now defaults to enabling branch protection using AArch64 pointer +authentication, if the target architecture version supports it. +Debian's base supported architecture does not, but Armv8.4-A does. So +when I changed the compile flags for enable_dit.c to add +-march=armv8.4-a, it didn't _just_ allow me to write the 'msr dit, %0' +instruction in my asm statement; it also unexpectedly turned on +pointer authentication in the containing function, which caused a +SIGILL when running on a pre-Armv8.4-A CPU, because although the code +correctly skipped the instruction that set DIT, it was already inside +enable_dit() at that point and couldn't avoid going through the +unsupported 'retaa' instruction which tries to check an auth code on +the return address. + +An obvious approach would be to add -mbranch-protection=none to the +compile flags for enable_dit.c. Another approach is to leave the +_compiler_ flags alone, and change the architecture in the assembler, +either via a fiddly -Wa,... option or by putting a .arch directive +inside the asm statement. But both have downsides. Turning off branch +protection is fine for the Debian build, but has the unwanted side +effect of turning it off (in that one function) even in builds +targeting a later architecture which _did_ want branch protection. And +changing the assembler's architecture risks changing it _down_ instead +of up, again perhaps invalidating other instructions generated by the +compiler (like if some later security feature is introduced that gcc +also wants to turn on by default). + +So instead I've taken the much simpler approach of not bothering to +change the target architecture at all, and instead generating the move +into DIT by hardcoding its actual instruction encoding. This meant I +also had to force the input value into a specific register, but I +don't think that does any harm (not _even_ wasting an extra +instruction in codegen). Now we should avoid interfering with any +security features the compiler wants to turn on or off: all of that +should be independent of the instruction I really wanted. +--- + crypto/CMakeLists.txt | 11 +++++++++-- + crypto/enable_dit.c | 6 +++++- + 2 files changed, 14 insertions(+), 3 deletions(-) + +diff -ru ../putty-0.83.orig/crypto/CMakeLists.txt ./crypto/CMakeLists.txt +--- ../putty-0.83.orig/crypto/CMakeLists.txt Sat Feb 1 22:20:18 2025 ++++ ./crypto/CMakeLists.txt Mon Mar 17 09:41:58 2025 +@@ -237,9 +237,16 @@ + endif() + + test_compile_with_flags(HAVE_ARM_DIT +- GNU_FLAGS -march=armv8.4-a + TEST_SOURCE " +- int main(void) { asm volatile(\"msr dit, %0\" :: \"r\"(1)); }" ++ #ifndef __aarch64__ ++ #error make sure this only even tries to work on AArch64 ++ #endif ++ #include <stdint.h> ++ int main(void) { ++ register uint64_t one asm(\"x8\"); ++ one = 1; ++ asm volatile(\".inst 0xd51b42a8\" :: \"r\"(one)); ++ }" + ADD_SOURCES_IF_SUCCESSFUL enable_dit.c) + + set(HAVE_AES_NI ${HAVE_AES_NI} PARENT_SCOPE) +diff -ru ../putty-0.83.orig/crypto/enable_dit.c ./crypto/enable_dit.c +--- ../putty-0.83.orig/crypto/enable_dit.c Sat Feb 1 22:20:18 2025 ++++ ./crypto/enable_dit.c Mon Mar 17 09:41:58 2025 +@@ -20,5 +20,9 @@ + { + if (!platform_dit_available()) + return; +- asm volatile("msr dit, %0" :: "r"(1)); ++ register uint64_t one asm("x8"); ++ one = 1; ++ // This is the binary encoding of "msr dit, x8". You can check via, e.g., ++ // echo "msr dit,x8" | llvm-mc -triple aarch64 -mattr=+dit -show-encoding ++ asm volatile(".inst 0xd51b42a8" :: "r"(one)); + } -- Darren Tucker (dtucker at dtucker.net) GPG key 11EAA6FA / A86E 3E07 5B19 5880 E860 37F4 9357 ECEF 11EA A6FA Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.