about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-09-08 16:00:25 -0700
committerUlrich Drepper <drepper@redhat.com>2009-09-08 16:00:25 -0700
commit6dfeb5245bca9f2ef94815ed9a7b979a9e0be744 (patch)
tree074284a8c86eae968f6f6693af669064a7edfcbe
parent3d60eb17340768688bd287580c32365c1e925487 (diff)
downloadglibc-6dfeb5245bca9f2ef94815ed9a7b979a9e0be744.tar.gz
glibc-6dfeb5245bca9f2ef94815ed9a7b979a9e0be744.tar.xz
glibc-6dfeb5245bca9f2ef94815ed9a7b979a9e0be744.zip
Fix __longjmp_chk on s390/s390x.
s390/s390x hasn't been updated to handle alternate stacks properly.
-rw-r--r--ChangeLog7
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c (renamed from sysdeps/s390/s390-32/____longjmp_chk.c)16
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c (renamed from sysdeps/s390/s390-64/____longjmp_chk.c)16
3 files changed, 37 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index d6cd79dfbb..1ae8348773 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-09-08  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/s390/s390-32/____longjmp_chk.c: Removed.
+	* sysdeps/s390/s390-64/____longjmp_chk.c: Removed.
+	* sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c: New file.
+	* sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c: New file.
+
 2009-09-07  Ulrich Drepper  <drepper@redhat.com>
 
 	* locale/programs/ld-collate.c (struct locale_collate_t): Add
diff --git a/sysdeps/s390/s390-32/____longjmp_chk.c b/sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c
index c5eb721e0e..b28e587498 100644
--- a/sysdeps/s390/s390-32/____longjmp_chk.c
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c
@@ -24,6 +24,9 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <signal.h>
+#include <sys/syscall.h>
 
 #define __longjmp ____longjmp_chk
 
@@ -35,7 +38,18 @@
       __asm ("lr %0, %%r15" : "=r" (cur_sp));				\
       new_sp ^= guard;							\
       if (new_sp < cur_sp)						\
-	__fortify_fail ("longjmp causes uninitialized stack frame");	\
+	{								\
+	  stack_t oss;							\
+	  INTERNAL_SYSCALL_DECL (err);					\
+	  int res = INTERNAL_SYSCALL (sigaltstack, err, 2, NULL, &oss);	\
+	  if (!INTERNAL_SYSCALL_ERROR_P (res, err))			\
+	    {								\
+	      if ((oss.ss_flags & SS_ONSTACK) == 0			\
+		  || ((uintptr_t) (oss.ss_sp + oss.ss_size) - new_sp	\
+		      >= oss.ss_size))					\
+		__fortify_fail ("longjmp causes uninitialized stack frame");\
+	    }								\
+	}								\
     } while (0)
 
 #include "__longjmp.c"
diff --git a/sysdeps/s390/s390-64/____longjmp_chk.c b/sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c
index 241822ce4a..dcf58fb50b 100644
--- a/sysdeps/s390/s390-64/____longjmp_chk.c
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c
@@ -24,6 +24,9 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <stdint.h>
+#include <signal.h>
+#include <sys/syscall.h>
 
 #define __longjmp ____longjmp_chk
 
@@ -35,7 +38,18 @@
       __asm ("lgr %0, %%r15" : "=r" (cur_sp));				\
       new_sp ^= guard;							\
       if (new_sp < cur_sp)						\
-	__fortify_fail ("longjmp causes uninitialized stack frame");	\
+	{								\
+	  stack_t oss;							\
+	  INTERNAL_SYSCALL_DECL (err);					\
+	  int res = INTERNAL_SYSCALL (sigaltstack, err, 2, NULL, &oss);	\
+	  if (!INTERNAL_SYSCALL_ERROR_P (res, err))			\
+	    {								\
+	      if ((oss.ss_flags & SS_ONSTACK) == 0			\
+		  || ((uintptr_t) (oss.ss_sp + oss.ss_size) - new_sp	\
+		      >= oss.ss_size))					\
+		__fortify_fail ("longjmp causes uninitialized stack frame");\
+	    }								\
+	}								\
     } while (0)
 
 #include "__longjmp.c"