[klibc] Bug#943425: Debian #943425: klibc: [s390x] setjmp/longjmp do not save/restore all registers in use

Thorsten Glaser tg at mirbsd.de
Wed May 5 12:56:30 PDT 2021


Ben Hutchings dixit:

>> > hpa, maks, bwh: any of you taking these two or should I send patches
>> > and possibly NMU klibc in Debian?
>>
>> Please send patches.  If you have a test base that could catch bugs
>
>test *case*
>
>> like this (without writing lists of registers in the test itself), that
>> would be really useful.

Unfortunately, I do not, other than, “run mksh’s testsuite”. This
seems to highly depend on compiler decisions (what to spill where
and when).

Patches for klibc upstream git attched; I’m currently trying to test
them, will report.

bye,
//mirabilos
-- 
Solange man keine schmutzigen Tricks macht, und ich meine *wirklich*
schmutzige Tricks, wie bei einer doppelt verketteten Liste beide
Pointer XORen und in nur einem Word speichern, funktioniert Boehm ganz
hervorragend.		-- Andreas Bogk über boehm-gc in d.a.s.r
-------------- next part --------------
From ba9cce08553cb49fe077485b13ae99548bb2da5c Mon Sep 17 00:00:00 2001
From: mirabilos <tg at debian.org>
Date: Wed, 5 May 2021 21:02:37 +0200
Subject: [PATCH 1/2] [klibc] sig{set,long}jmp: do not ignore sigsetjmp's
 second argument

Save and restore the signal mask only if that argument is nonzero,
as required by the standards.  (Closes: Debian #988027)

Signed-off-by: mirabilos <tg at debian.org>
---
 usr/include/setjmp.h   | 7 ++++++-
 usr/klibc/CAVEATS      | 3 +--
 usr/klibc/siglongjmp.c | 3 ++-
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/usr/include/setjmp.h b/usr/include/setjmp.h
index abebccde..5916cd8a 100644
--- a/usr/include/setjmp.h
+++ b/usr/include/setjmp.h
@@ -27,6 +27,7 @@ __extern __noreturn longjmp(jmp_buf, int);
 struct __sigjmp_buf {
 	jmp_buf __jmpbuf;
 	sigset_t __sigs;
+	unsigned char __sigs_saved;
 };
 
 typedef struct __sigjmp_buf sigjmp_buf[1];
@@ -34,7 +35,11 @@ typedef struct __sigjmp_buf sigjmp_buf[1];
 #define sigsetjmp(__env, __save) \
 ({ \
   struct __sigjmp_buf *__e = (__env); \
-  sigprocmask(0, NULL, &__e->__sigs); \
+  if (__save) { \
+    sigprocmask(0, NULL, &__e->__sigs); \
+    __e->__sigs_saved = 1; \
+  } else \
+    __e->__sigs_saved = 0; \
   setjmp(__e->__jmpbuf); \
 })
 
diff --git a/usr/klibc/CAVEATS b/usr/klibc/CAVEATS
index 5e991cb7..39949c28 100644
--- a/usr/klibc/CAVEATS
+++ b/usr/klibc/CAVEATS
@@ -13,8 +13,7 @@ Compiling with -O0 is more likely to work on gcc 3.
 setjmp()/longjmp():
 -------------------
 setjmp() and longjmp() *do not* save signal state.  sigsetjmp() and
-siglongjmp() *do* save the signal mask -- regardless of the value of
-the extra argument.
+siglongjmp() *do* save the signal mask if the extra argument is nonzero.
 
 The standards actually state that if you pass longjmp() a final value
 of zero the library should change that to a 1!  Presumably the reason
diff --git a/usr/klibc/siglongjmp.c b/usr/klibc/siglongjmp.c
index 31042cbd..45f4e400 100644
--- a/usr/klibc/siglongjmp.c
+++ b/usr/klibc/siglongjmp.c
@@ -10,6 +10,7 @@
 
 __noreturn siglongjmp(sigjmp_buf buf, int retval)
 {
-	sigprocmask(SIG_SETMASK, &buf->__sigs, NULL);
+	if (buf->__sigs_saved)
+		sigprocmask(SIG_SETMASK, &buf->__sigs, NULL);
 	longjmp(buf->__jmpbuf, retval);
 }
-- 
2.31.1

-------------- next part --------------
From fc5a53932ee56d61a9fd8db75784e9f39ca474a3 Mon Sep 17 00:00:00 2001
From: mirabilos <tg at debian.org>
Date: Wed, 5 May 2021 21:26:33 +0200
Subject: [PATCH 2/2] [klibc] {set,long}jmp [s390x]: save/restore the correct
 registers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The s390x ABI actually has FPU registers f8‥f15, not f1/f3/f5/f7,
to be saved. (Closes: Debian #943425)

Signed-off-by: mirabilos <tg at debian.org>
---
 usr/include/arch/s390/klibc/archsetjmp.h |  2 +-
 usr/klibc/arch/s390/setjmp.S             | 24 ++++++++++++++++--------
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/usr/include/arch/s390/klibc/archsetjmp.h b/usr/include/arch/s390/klibc/archsetjmp.h
index 728780ad..1167c8b6 100644
--- a/usr/include/arch/s390/klibc/archsetjmp.h
+++ b/usr/include/arch/s390/klibc/archsetjmp.h
@@ -16,7 +16,7 @@ struct __jmp_buf {
 
 struct __jmp_buf {
 	uint64_t __gregs[10]; /* general registers r6-r15 */
-	uint64_t __fpregs[4]; /* fp registers f1, f3, f5, f7 */
+	uint64_t __fpregs[8]; /* fp registers f8-f15 */
 };
 
 #endif /* __s390x__ */
diff --git a/usr/klibc/arch/s390/setjmp.S b/usr/klibc/arch/s390/setjmp.S
index c36a0517..1386419a 100644
--- a/usr/klibc/arch/s390/setjmp.S
+++ b/usr/klibc/arch/s390/setjmp.S
@@ -38,10 +38,14 @@ longjmp:
 
 setjmp:
 	stmg	%r6,%r15,0(%r2)		# save all general registers
-	std	%f1,80(%r2)		# save fp registers f4 and f6
-	std	%f3,88(%r2)
-	std	%f5,96(%r2)
-	std	%f7,104(%r2)
+	std	%f8,80(%r2)		# save fp registers f8 to f15
+	std	%f9,88(%r2)
+	std	%f10,96(%r2)
+	std	%f11,104(%r2)
+	std	%f12,112(%r2)
+	std	%f13,120(%r2)
+	std	%f14,128(%r2)
+	std	%f15,136(%r2)
 	lghi	%r2,0			# return 0
 	br	%r14
 
@@ -54,10 +58,14 @@ setjmp:
 longjmp:
 	lgr	%r1,%r2			# jmp_buf
 	lgr	%r2,%r3			# return value
-	ld	%f7,104(%r1)		# restore all saved registers
-	ld	%f5,96(%r1)
-	ld	%f3,88(%r1)
-	ld	%f1,80(%r1)
+	ld	%f15,136(%r1)		# restore all saved registers
+	ld	%f14,128(%r1)
+	ld	%f13,120(%r1)
+	ld	%f12,112(%r1)
+	ld	%f11,104(%r1)
+	ld	%f10,96(%r1)
+	ld	%f9,88(%r1)
+	ld	%f8,80(%r1)
 	lmg	%r6,%r15,0(%r1)
 	br	%r14			# return to restored address
 
-- 
2.31.1



More information about the klibc mailing list