[git commit] tls: P256: fix obscure x86_64 asm misbehavior, closes 15679

Denys Vlasenko vda.linux at googlemail.com
Thu Jul 11 21:53:47 UTC 2024


commit: https://git.busybox.net/busybox/commit/?id=d745852f136bac4646e50a4f03565273e687b28b
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

gcc does not necessarily clear upper bits in
64-bit regs if you ask it to load a 32-bit constant.

Cast it to unsigned long. Better yet, hand-write loading
of the constant with a smaller instruction.

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/tls_sp_c32.c | 39 +++++++++++++++++++++++++++++----------
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c
index a593c5c40..9ab996f3b 100644
--- a/networking/tls_sp_c32.c
+++ b/networking/tls_sp_c32.c
@@ -425,26 +425,45 @@ static void sp_256_sub_8_p256_mod(sp_digit* r)
 #elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__)
 static void sp_256_sub_8_p256_mod(sp_digit* r)
 {
+//p256_mod[3..0] = ffffffff00000001 0000000000000000 00000000ffffffff ffffffffffffffff
+# if 0
+	// gcc -Oz bug (?) https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115875
+	// uses buggy "push $-1; pop %rax" insns to load 00000000ffffffff
 	uint64_t reg;
 	uint64_t ooff;
-//p256_mod[3..0] = ffffffff00000001 0000000000000000 00000000ffffffff ffffffffffffffff
 	asm volatile (
-"\n		addq	$1, (%0)"	// adding 1 is the same as subtracting ffffffffffffffff
-"\n		cmc"			// only carry bit needs inverting
-"\n"
-"\n		sbbq	%1, 1*8(%0)"	// %1 holds 00000000ffffffff
-"\n"
+"\n		subq	$0xffffffffffffffff, (%0)"
+"\n		sbbq	%1, 1*8(%0)"
 "\n		sbbq	$0, 2*8(%0)"
-"\n"
 "\n		movq	3*8(%0), %2"
-"\n		sbbq	$0, %2"		// adding 00000000ffffffff (in %1)
-"\n		addq	%1, %2"		// is the same as subtracting ffffffff00000001
+"\n		sbbq	$0, %2"	// subtract carry
+"\n		addq	%1, %2" // adding 00000000ffffffff (in %1)
+"\n"		// is the same as subtracting ffffffff00000001
 "\n		movq	%2, 3*8(%0)"
 "\n"
 		: "=r" (r), "=r" (ooff), "=r" (reg)
-		: "0" (r), "1" (0x00000000ffffffff)
+		: "0" (r), "1" (0x00000000ffffffffUL) /* UL is important! */
+		: "memory"
+	);
+# else // let's do it by hand:
+	uint64_t reg;
+	uint64_t rax;
+	asm volatile (
+"\n		orl	$0xffffffff, %%eax" // %1 (rax) = 00000000ffffffff
+"\n		subq	$0xffffffffffffffff, (%0)"
+"\n		sbbq	%1, 1*8(%0)"
+"\n		sbbq	$0, 2*8(%0)"
+"\n		movq	3*8(%0), %2"
+"\n		sbbq	$0, %2"	// subtract carry
+"\n		addq	%1, %2" // adding 00000000ffffffff (in %1)
+"\n"		// is the same as subtracting ffffffff00000001
+"\n		movq	%2, 3*8(%0)"
+"\n"
+		: "=r" (r), "=&a" (rax), "=r" (reg)
+		: "0" (r)
 		: "memory"
 	);
+# endif
 }
 #else
 static void sp_256_sub_8_p256_mod(sp_digit* r)


More information about the busybox-cvs mailing list