aboutsummaryrefslogtreecommitdiffstats
path: root/libc
diff options
context:
space:
mode:
authorJosh Gao <jmgao@google.com>2016-03-29 14:03:09 -0700
committerJosh Gao <jmgao@google.com>2016-03-29 18:07:32 -0700
commit7af64bd083a86df3ec2322892a5fcfcc075c2114 (patch)
tree7b81e459b106ac03ac1e5465da72a6eae7d61600 /libc
parent9ce09e423f24823d52f19ab8247e078977100132 (diff)
downloadandroid_bionic-7af64bd083a86df3ec2322892a5fcfcc075c2114.tar.gz
android_bionic-7af64bd083a86df3ec2322892a5fcfcc075c2114.tar.bz2
android_bionic-7af64bd083a86df3ec2322892a5fcfcc075c2114.zip
Add a checksum to jmp_buf on x86.
Bug: http://b/27856501 Bug: http://b/27417786 Change-Id: Id5a0a81fc38e311bff678cbc7dc2219bc0074503 (cherry picked from commit 926078539346f5d3cc864c9ba25993e8c6437c07)
Diffstat (limited to 'libc')
-rw-r--r--libc/arch-x86/bionic/setjmp.S39
1 files changed, 38 insertions, 1 deletions
diff --git a/libc/arch-x86/bionic/setjmp.S b/libc/arch-x86/bionic/setjmp.S
index 86e6e3cd5..efb645993 100644
--- a/libc/arch-x86/bionic/setjmp.S
+++ b/libc/arch-x86/bionic/setjmp.S
@@ -32,6 +32,21 @@
#include <private/bionic_asm.h>
+// The internal structure of a jmp_buf is totally private.
+// Current layout (changes from release to release):
+//
+// word name description
+// 0 edx registers
+// 1 ebx
+// 2 esp
+// 3 ebp
+// 4 esi
+// 5 edi
+// 6 sigmask signal mask (not used with _setjmp / _longjmp)
+// 7 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
+// 8 checksum checksum of the core registers, to give better error messages.
+// 9 reserved
+
#define _JB_EDX 0
#define _JB_EBX 1
#define _JB_ESP 2
@@ -40,6 +55,7 @@
#define _JB_EDI 5
#define _JB_SIGMASK 6
#define _JB_SIGFLAG 7
+#define _JB_CHECKSUM 8
.macro m_mangle_registers reg
xorl \reg,%edx
@@ -54,6 +70,13 @@
m_mangle_registers \reg
.endm
+.macro m_calculate_checksum dst, src
+ movl $0, \dst
+ .irp i,0,1,2,3,4,5
+ xorl (\i*4)(\src), \dst
+ .endr
+.endm
+
ENTRY(setjmp)
movl 4(%esp),%ecx
mov $1,%eax
@@ -111,13 +134,22 @@ ENTRY(sigsetjmp)
movl %edi,(_JB_EDI * 4)(%ecx)
m_unmangle_registers %eax
+ m_calculate_checksum %eax, %ecx
+ movl %eax, (_JB_CHECKSUM * 4)(%ecx)
+
xorl %eax,%eax
ret
END(sigsetjmp)
ENTRY(siglongjmp)
- // Do we have a signal mask to restore?
movl 4(%esp),%edx
+
+ // Check the checksum before doing anything.
+ m_calculate_checksum %eax, %edx
+ xorl (_JB_CHECKSUM * 4)(%edx), %eax
+ jnz 3f
+
+ // Do we have a signal mask to restore?
movl (_JB_SIGFLAG * 4)(%edx), %eax
testl $1,%eax
jz 1f
@@ -165,6 +197,11 @@ ENTRY(siglongjmp)
2:
movl %ecx,0(%esp)
ret
+
+3:
+ PIC_PROLOGUE
+ pushl (_JB_SIGMASK * 4)(%edx)
+ call PIC_PLT(__bionic_setjmp_checksum_mismatch)
END(siglongjmp)
ALIAS_SYMBOL(longjmp, siglongjmp)